161 lines
4.5 KiB
Plaintext
161 lines
4.5 KiB
Plaintext
{{task heading|AST interpreter}}
|
|
|
|
An AST interpreter interprets an [https://en.wikipedia.org/wiki/Abstract_syntax_tree Abstract Syntax Tree (AST)]
|
|
produced by a [[Compiler/syntax_analyzer|Syntax Analyzer]].
|
|
|
|
;Task
|
|
|
|
Take the AST output from the Syntax analyzer [[Compiler/syntax_analyzer|task]], and interpret it as appropriate.
|
|
Refer to the [[Compiler/syntax_analyzer|Syntax analyzer task]] for details of the AST.
|
|
|
|
;Loading the AST from the syntax analyzer is as simple as (pseudo code):
|
|
|
|
<syntaxhighlight lang="python">def load_ast()
|
|
line = readline()
|
|
# Each line has at least one token
|
|
line_list = tokenize the line, respecting double quotes
|
|
|
|
text = line_list[0] # first token is always the node type
|
|
|
|
if text == ";" # a terminal node
|
|
return NULL
|
|
|
|
node_type = text # could convert to internal form if desired
|
|
|
|
# A line with two tokens is a leaf node
|
|
# Leaf nodes are: Identifier, Integer, String
|
|
# The 2nd token is the value
|
|
if len(line_list) > 1
|
|
return make_leaf(node_type, line_list[1])
|
|
|
|
left = load_ast()
|
|
right = load_ast()
|
|
return make_node(node_type, left, right)</syntaxhighlight>
|
|
|
|
; The interpreter algorithm is relatively simple:
|
|
|
|
<syntaxhighlight lang="python">interp(x)
|
|
if x == NULL return NULL
|
|
elif x.node_type == Integer return x.value converted to an integer
|
|
elif x.node_type == Ident return the current value of variable x.value
|
|
elif x.node_type == String return x.value
|
|
elif x.node_type == Assign
|
|
globals[x.left.value] = interp(x.right)
|
|
return NULL
|
|
elif x.node_type is a binary operator return interp(x.left) operator interp(x.right)
|
|
elif x.node_type is a unary operator, return return operator interp(x.left)
|
|
elif x.node_type == If
|
|
if (interp(x.left)) then interp(x.right.left)
|
|
else interp(x.right.right)
|
|
return NULL
|
|
elif x.node_type == While
|
|
while (interp(x.left)) do interp(x.right)
|
|
return NULL
|
|
elif x.node_type == Prtc
|
|
print interp(x.left) as a character, no newline
|
|
return NULL
|
|
elif x.node_type == Prti
|
|
print interp(x.left) as an integer, no newline
|
|
return NULL
|
|
elif x.node_type == Prts
|
|
print interp(x.left) as a string, respecting newlines ("\n")
|
|
return NULL
|
|
elif x.node_type == Sequence
|
|
interp(x.left)
|
|
interp(x.right)
|
|
return NULL
|
|
else
|
|
error("unknown node type")</syntaxhighlight>
|
|
|
|
Notes:
|
|
|
|
Because of the simple nature of our tiny language, Semantic analysis is not needed.
|
|
|
|
Your interpreter should use C like division semantics, for both division and modulus. For division of positive operands, only the non-fractional portion of the result should be returned. In other words, the result should be truncated towards 0.
|
|
|
|
This means, for instance, that 3 / 2 should result in 1.
|
|
|
|
For division when one of the operands is negative, the result should be truncated towards 0.
|
|
|
|
This means, for instance, that 3 / -2 should result in -1.
|
|
|
|
; Test program
|
|
|
|
{| class="wikitable"
|
|
|-
|
|
! prime.t
|
|
! lex <prime.t | parse | interp
|
|
|-
|
|
| style="vertical-align:top" |
|
|
<syntaxhighlight lang="c">/*
|
|
Simple prime number generator
|
|
*/
|
|
count = 1;
|
|
n = 1;
|
|
limit = 100;
|
|
while (n < limit) {
|
|
k=3;
|
|
p=1;
|
|
n=n+2;
|
|
while ((k*k<=n) && (p)) {
|
|
p=n/k*k!=n;
|
|
k=k+2;
|
|
}
|
|
if (p) {
|
|
print(n, " is prime\n");
|
|
count = count + 1;
|
|
}
|
|
}
|
|
print("Total primes found: ", count, "\n"); </syntaxhighlight>
|
|
|
|
| style="vertical-align:top" |
|
|
<b><pre>
|
|
3 is prime
|
|
5 is prime
|
|
7 is prime
|
|
11 is prime
|
|
13 is prime
|
|
17 is prime
|
|
19 is prime
|
|
23 is prime
|
|
29 is prime
|
|
31 is prime
|
|
37 is prime
|
|
41 is prime
|
|
43 is prime
|
|
47 is prime
|
|
53 is prime
|
|
59 is prime
|
|
61 is prime
|
|
67 is prime
|
|
71 is prime
|
|
73 is prime
|
|
79 is prime
|
|
83 is prime
|
|
89 is prime
|
|
97 is prime
|
|
101 is prime
|
|
Total primes found: 26
|
|
</pre></b>
|
|
|
|
|}
|
|
|
|
; Additional examples
|
|
|
|
Your solution should pass all the test cases above and the additional tests found '''[[Compiler/Sample_programs|Here]]'''.
|
|
|
|
{{task heading|Reference}}
|
|
|
|
The C and Python versions can be considered reference implementations.
|
|
|
|
;Related Tasks
|
|
|
|
* [[Compiler/lexical_analyzer|Lexical Analyzer task]]
|
|
* [[Compiler/syntax_analyzer|Syntax Analyzer task]]
|
|
* [[Compiler/code_generator|Code Generator task]]
|
|
* [[Compiler/virtual_machine_interpreter|Virtual Machine Interpreter task]]
|
|
|
|
<hr>
|
|
__TOC__
|
|
|