Compiler/AST interpreter: Difference between revisions
Content deleted Content added
Line 2,135:
Total primes found: 26
</pre>
=={{header|Nim}}==
Using AST produced by the parser from the task “syntax analyzer”.
<lang Nim>import os, strutils, streams, tables
import ast_parser
type
ValueKind = enum valNil, valInt, valString
# Representation of a value.
Value = object
case kind: ValueKind
of valNil: nil
of valInt: intVal: int
of valString: stringVal: string
# Range of binary operators.
BinaryOperator = range[nMultiply..nOr]
# Table of variables.
var variables: Table[string, Value]
type RunTimeError = object of CatchableError
#---------------------------------------------------------------------------------------------------
template newInt(val: typed): Value =
## Create an integer value.
Value(kind: valInt, intVal: val)
#---------------------------------------------------------------------------------------------------
proc interp(node: Node): Value =
## Interpret code starting at "node".
if node.isNil:
return Value(kind: valNil)
case node.kind
of nInteger:
result = Value(kind: valInt, intVal: node.intVal)
of nIdentifier:
if node.name notin variables:
raise newException(RunTimeError, "Variable {node.name} is not initialized.")
result = variables[node.name]
of nString:
result = Value(kind: valString, stringVal: node.stringVal)
of nAssign:
variables[node.left.name] = interp(node.right)
of nNegate:
result = newInt(-interp(node.left).intVal)
of nNot:
result = newInt(not interp(node.left).intVal)
of BinaryOperator.low..BinaryOperator.high:
let left = interp(node.left)
let right = interp(node.right)
case BinaryOperator(node.kind)
of nMultiply:
result = newInt(left.intVal * right.intVal)
of nDivide:
result = newInt(left.intVal div right.intVal)
of nMod:
result = newInt(left.intVal mod right.intVal)
of nAdd:
result = newInt(left.intVal + right.intVal)
of nSubtract:
result = newInt(left.intVal - right.intVal)
of nLess:
result = newInt(ord(left.intVal < right.intVal))
of nLessEqual:
result = newInt(ord(left.intVal <= right.intVal))
of nGreater:
result = newInt(ord(left.intVal > right.intVal))
of nGreaterEqual:
result = newInt(ord(left.intVal >= right.intVal))
of nEqual:
result = newInt(ord(left.intVal == right.intVal))
of nNotEqual:
result = newInt(ord(left.intVal != right.intVal))
of nAnd:
result = newInt(left.intVal and right.intVal)
of nOr:
result = newInt(left.intVal or right.intVal)
of nIf:
if interp(node.left).intVal != 0:
discard interp(node.right.left)
else:
discard interp(node.right.right)
of nWhile:
while interp(node.left).intVal != 0:
discard interp(node.right)
of nPrtc:
stdout.write(chr(interp(node.left).intVal))
of nPrti:
stdout.write(interp(node.left).intVal)
of nPrts:
stdout.write(interp(node.left).stringVal)
of nSequence:
discard interp(node.left)
discard interp(node.right)
#---------------------------------------------------------------------------------------------------
proc loadAst(stream: Stream): Node =
## Load a linear AST and build a binary tree.
let line = stream.readLine().strip()
if line.startsWith(';'):
return nil
var fields = line.split(' ', 1)
let kind = parseEnum[NodeKind](fields[0])
if kind in {nIdentifier, nString, nInteger}:
if fields.len < 2:
raise newException(ValueError, "Missing value field for " & fields[0])
else:
fields[1] = fields[1].strip()
case kind
of nIdentifier:
return Node(kind: nIdentifier, name: fields[1])
of nString:
return Node(kind: nString, stringVal: unescape(fields[1]).replace("\\n", "\n"))
of nInteger:
return Node(kind: nInteger, intVal: parseInt(fields[1]))
else:
if fields.len > 1:
raise newException(ValueError, "Extra field for " & fields[0])
let left = stream.loadAst()
let right = stream.loadAst()
result = newNode(kind, left, right)
#———————————————————————————————————————————————————————————————————————————————————————————————————
var stream: Stream
var toClose = false
if paramCount() < 1:
stream = newFileStream(stdin)
else:
stream = newFileStream(paramStr(1))
toClose = true
let ast = loadAst(stream)
if toClose: stream.close()
discard ast.interp()</lang>
=={{header|Perl}}==
|