How x = 2; print x; becomes output
Gregory S. DeLozier, PhD
x = 2;
print x;
2
What must the interpreter remember?
An expression produces a value.
x + 3 * 4
A statement performs an action.
x = 2
print x
program ::= statement_list
statement ::= assignment_statement
| print_statement
A statement list contains at least one statement.
| Source | Valid? |
|---|---|
x = 2 |
Yes |
x = 2; print x |
Yes |
;;;x = 2;;;print x;;; |
Yes |
x = 2 print x |
No |
| empty input | No |
x = 2; // Keep the separator.
print x
The newline does not replace the semicolon.
x = 2 // ; is part of the comment.
print x
The second program has no separator between statements.
statement_list ::= { ";" } statement
{ ";" { ";" } statement }
{ ";" }
Braces mean zero or more repetitions.
assignment_statement ::= <identifier> "=" expression
print_statement ::= "print" expression
x = 2
print x
factor ::= <number>
| <identifier>
| "(" expression ")"
y = x + 3 * 4
What value does x have?
term ::= unary { ("*" | "/") unary }
unary ::= "-" unary | factor
x = -1.5
y = 3 * -2
program
statement_list
assign
target: identifier x
expression: number 2
print
identifier x
The tree preserves statement order.
An environment maps names to values.
| Name | Value |
|---|---|
x |
2 |
The program begins with an empty environment.
x = 2
2.x.{} becomes {"x": 2}
print x
x.2.2.An unknown name causes an evaluation error.
Search here, then outward. The first binding wins.
| Lookup | Result |
|---|---|
x |
3 from the current environment |
y |
20 from the enclosing environment |
z |
Error: no binding in the chain |
Assignment stays local: y = 7 leaves
the parent’s y at 20.
| Statement | Environment afterward | Output |
|---|---|---|
x = 2 |
{"x": 2} |
|
print x |
{"x": 2} |
2 |
y = x + 3 * 4 |
{"x": 2, "y": 14} |
|
print y |
{"x": 2, "y": 14} |
14 |
Valid:
x = 2;
print x;
Invalid in Topic 2:
print (x = 2)
case token.ADD, token.SUB, token.NOT,
token.XOR, token.AND, token.TILDE:
pos, op := p.pos, p.tok
p.next()
x := p.parseUnaryExpr()
return &ast.UnaryExpr{OpPos: pos, Op: op, X: x}Same move: consume the operator, parse the operand, build a tree node.
Vertex can now:
The next lecture follows these rules through the code.