semantics = {
const context = new Map()
return g.createSemantics().addOperation('ast', {
Program(statements) {
return new core.Program(statements.ast())
},
Stmt(argument) {
return new core.Statement(argument.ast())
},
Block(body) {
return new core.Block(body.ast())
},
FnCall(_left, fnName, _dots, params, _right) {
return new core.FnCall(fnName.sourceString, params.ast())
},
VarDec(_left, _def, id, _dots, exp, _right) {
const variable = new core.Variable(id.sourceString, 'any')
const initializer = exp.ast()
context.set(variable.name, variable)
return new core.VarDec(variable, initializer)
},
Exp_binary(left, op, right) {
return new core.BinaryExpression(op.sourceString, left.ast(), right.ast())
},
Condition_binary(left, op, right) {
return new core.BinaryExpression(op.sourceString, left.ast(), right.ast())
},
Term_binary(left, op, right) {
return new core.BinaryExpression(op.sourceString, left.ast(), right.ast())
},
Factor_binary(left, op, right) {
return new core.BinaryExpression(op.sourceString, left.ast(), right.ast())
},
Exp(val) {
return new core.Expression(val.ast())
},
Var(val) {
const entity = context.get(val.sourceString)
if (!entity) throw new Error(`Identifier "${val.sourceString}" not declared`)
return entity
},
true(_) {
return true
},
false(_) {
return false
},
intlit(digits) {
return parseInt(digits.ast())
},
floatlit(digits1, dot, digits2) {
return parseFloat(digits1.ast() + '.' + digits2.ast())
},
strlit(a1, chars, a2) {
return chars.ast().join('')
},
_terminal() {
return this.sourceString
},
_iter(...children) {
return children.map(c => c.ast())
}
})}