Abstract Syntax Different Levels of Syntax • Lexical syntax – Basic symbols (names, values, operators, etc.) • Concrete syntax – Rules for writing expressions, statements, programs – Input to compilers/interpreters • Abstract syntax – “Internal” representation – Captures semantics CS784(PM) 2 Overview Parse-expression Concrete Syntax Abstract Syntax Unparse-expression Interpreter Results CS784(PM) 3 Concrete vs. Abstract Syntax • Expressions with common meaning (should) have the same abstract syntax. – C: a+b*c • Assumes certain operator precedence (why?) – Forth: bc*a+ (reverse Polish) This expression tree represents the meaning of expression Not the same as parse tree (why?) Does the value depend on traversal order? abc*+ (or is this it?) CS784(PM) 4 Parse tree vs. AST expr + expr expr expr expr 1 + expr + ( CS784(PM) 2 expr ) + ( 3 ) 1 2 3 5 Abstract Syntax Tree • More useful representation of syntax tree – Less clutter – Actual level of detail depends on your design • Basis for semantic analysis • Later annotated with various information – Type information – Computed values CS784(PM) 6 Compilation in a Nutshell Source code (character stream) if (b == 0) a = b; Lexical analysis Token stream if ( b == 0 ) a = b ; Parsing if == Abstract syntax tree b 0 (AST) if boolean == Decorated AST int CS784(PM) b a int ; = b Semantic Analysis int = 0 int a lvalue ; int b 7 λ-expressions 1. <exp> ::= 2. <identifier> 3. | (lambda (<identifier> ) <exp>) 4. | (<exp> <exp>) • Compare with Scheme S-expressions. • EOPL3 p52: Lc-exp CS784(PM) 8 Lc-exp ::= • Identifier – var-exp (var) • (lambda (Identifier) Lc-exp) – lambda-exp (bound-var body) • (Lc-exp Lc-exp) – app-exp (rator rand) • Abstract syntax CS784(PM) 9 EOPL3 Scheme: define-datatype • Syntax definition: (define-datatype type-name type-predicate-name {(variant-name {(field-name predicate)}* )} + ) • An Example: (define-datatype environment environment? (empty-env-record) (extended-env-record (syms (list-of symbol?)) (vals (list-of scheme-value?)) (env environment?))) • Data types built by define-datatype may be mutually recursive. CS784(PM) 10 Syntax Driven Representation (define-datatype expression expression? (var-exp (id symbol?)) (lambda-exp (id symbol?) (body expression?)) (app-exp (rator expression?) (rand expression?))) CS784(PM) 11 Figure 2.2: (lambda (x) (f (f x))) CS784(PM) 12 Concrete to Abstract Syntax (define parse-expression (lambda (datum) (cond ((symbol? datum) (var-exp datum)) ((pair? datum) (if (eqv? (car datum) 'lambda) (lambda-exp (caadr datum) (parse-expression (caddr datum))) (app-exp (parse-expression (car datum)) (parse-expression (cadr datum)))) ) (else (eopl:error 'parse-expression "Invalid concrete syntax ~s" datum)) CS784(PM) ))) 13 DrRacket CS784(PM) 14 Unparse: Abstract to Concrete Syntax (define unparse-expression (lambda (exp) (cases expression exp (var-exp (id) id) (lambda-exp (id body) (list 'lambda (list id) (unparse-expression body)) ) (app-exp (rator rand) (list (unparse-expression rator) (unparse-expression rand)) )))) CS784(PM) 15 Role of Induction and Recursion • Define data structures (infinite values) by induction. – Seed elements. – Closure operations. • Define functions (operations) by recursion. – Boundary/Basis case. – Composite/Recursive case. • Prove properties using structural induction. – Basis case. – Inductive step. CS784(PM) 16 The Environment • Environment: – table of variable-value pairs – Chronologically later var-value pair overrides • Constructors – empty-env – extend-env • Observer – apply-env CS784(PM) 17 The Environment Spec • (empty-env) = ∅ • (apply-env f var) = f (var) • (extend-env var v f] ) = g, – where g(var1 ) = v, if var1 = var = f (var1). otherwise • from EOPL3 p36 CS784(PM) 18 An Example Env e • (define e (extend-env ’d 6 (extend-env ’y 8 (extend-env ’x 7 (extend-env ’y 14 (empty-env)))))) • e(d)=6, e(x)=7, e(y)=8 CS784(PM) 19 Representing Environment • • • • Many representations are possible Speedy access Memory frugal Change in the interface: Syms x Vals (define extend-env (lambda (syms vals env) … )) CS784(PM) 20 Alt-1: env is a List of Ribs • • • left rib: list of variables right rib: corresponding list of values. Exercise 2.11 EOPL3 (Ribcage) CS784(PM) 21 Alt-1: List of Ribs (Ribcage) (define empty-env (lambda () '())) (define extend-env (lambda (syms vals env) (cons (list syms vals) env) )) (define apply-env (lambda (env sym) (if (null? env) (eopl:error 'apply-env "No binding for ~s" sym) (let ((syms (car (car env))) (vals (cadr (car env))) (env (cdr env))) (let ((pos (rib-find-position sym syms))) (if (number? pos) (list-ref vals pos) (apply-env env sym))))))) CS784(PM) 22 Alt-2: env is a Unary Function (define empty-env (lambda () (lambda (sym) (eopl:error 'apply-env "No binding for ~s" sym)) )) (define extend-env (lambda (syms vals env) (lambda (sym) (let ((pos (list-find-position sym syms))) (if (number? pos) (list-ref vals pos) (apply-env env sym)))) )) (define apply-env (lambda (env sym) (env sym) )) CS784(PM) 23 Alt-3: Tagged Records (define-datatype environment environment? (empty-env-record) (extended-env-record (syms (list-of symbol?)) (vals (list-of scheme-value?)) (env environment?))) (define scheme-value? (lambda (v) #t)) (define empty-env (lambda () (empty-env-record) )) (define extend-env (lambda (syms vals env) (extended-env-record syms vals env))) CS784(PM) 24 Alt-3: Tagged records (define apply-env (lambda (env sym) (cases environment env (empty-env-record () (eopl:error 'apply-env "No binding for ~s" sym)) (extended-env-record (syms vals env) (let ((pos (list-find-position sym syms))) (if (number? pos) (list-ref vals pos) (apply-env env sym))))))) CS784(PM) 25 Queue (define (define (define (define (define reset empty? enqueue dequeue Q (lambda (lambda (lambda (lambda (q) (q) (q) (q) (vector-ref (vector-ref (vector-ref (vector-ref q q q q 0))) 1))) 2))) 3))) (create-queue)) ((enqueue Q) 55) ((empty? Q)) ((dequeue Q)) ((empty? Q)) ((reset Q)) ((dequeue Q)) CS784(PM) 26 1. (define create-queue 2. (lambda () 3. (let ((q-in '()) (q-out '())) 4. (letrec 5. ((reset-queue 6. (lambda () 7. (set! q-in '()) (set! q-out '())) ) 8. (empty-queue? 9. (lambda () 10. (and (null? q-in) (null? q-out))) ) 11. (enqueue 12. (lambda (x) 13. (set! q-in (cons x q-in))) ) 14. (dequeue 15. (lambda () 16. (if (empty-queue?) 17. (eopl:error 'dequeue "Not on an empty queue") 18. (begin 19. (if (null? q-out) 20. (begin 21. (set! q-out (reverse q-in)) (set! q-in '()))) 22. (let ((ans (car q-out))) 23. (set! q-out (cdr q-out)) 24. ans))))) ) 25. (vector reset-queue empty-queue? enqueue dequeue)) 26. ))) CS784(PM) 27