1 / 21

CPSC320 Tutorial 4

CPSC320 Tutorial 4. Data Abstraction Abstract Syntax 05 Oct. 2010 Narek Nalbandyan. Interfaces for Recursive Data Types. During previous tutorials we were mostly using recursive data types. Ex: LcExp ::= Identifier ::= (lambda (Identifier) LcExp)

erik
Télécharger la présentation

CPSC320 Tutorial 4

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. CPSC320 Tutorial 4 Data Abstraction Abstract Syntax 05 Oct. 2010 Narek Nalbandyan

  2. Interfaces for Recursive Data Types During previous tutorials we were mostly using recursive data types. Ex: LcExp ::= Identifier ::= (lambda (Identifier) LcExp) ::= (LcExp LcExp) and we wrote procedures like occurs-free?.

  3. Interfaces for Recursive Data Types cont… (define occurs-free? (lambda (var exp) (cond ((symbol? exp) (eqv? var exp)) ((eqv? (car exp) 'lambda) (and (not (eqv? var (car (cadr exp)))) (occurs-free? var (caddr exp)))) (else (or (occurs-free? var (car exp)) (occurs-free? var (cadr exp)))))))

  4. Interfaces for Recursive Data Types cont… As you see, the definition of occurs-free? is not as readable as it might be We can improve this situation by introducing an interface for lambda-calculus expressions Our interface will have constructors and two kinds of observers: predicates and extractors The constructors are: var-exp (define var-exp (lambda (var) `(var-exp ,var))) lambda-exp app-exp

  5. Interfaces for Recursive Data Types cont… The predicates are: var-exp? (define var-exp? (lambda (x) (and (pair? x) (eq? (car x) 'var-exp)))) lambda-exp? app-exp? The extractors are: var-exp->var (define var-exp->var (lambda (x) (cadr x))) lambda-exp->bound-var lambda-exp->body app-exp->rator app-exp->rand

  6. Interfaces for Recursive Data Types cont… (define occurs-free? (lambda (search-var exp) (cond ((var-exp? exp) (eqv? search-var (var-exp->var exp))) ((lambda-exp? exp) (and (not (eqv? search-var (lambda-exp->bound-var exp))) (occurs-free? search-var (lambda-exp->body exp)))) (else (or (occurs-free? search-var (app-exp->rator exp)) (occurs-free? search-var (app-exp->rand exp)))))))

  7. Interfaces for Recursive Data Types cont… Now we can write down a general recipe for designing an interface for recursive data type: Include one constructor for each kind of data type Include one predicate for each kind of data type Include one extractor for each piece of data passed to a constructor of the data type

  8. A Tool for Defining Recursive Data Types For complicated data types, applying the recipe for constructing an interface can quickly become tedious Now we will introduce a tool for automatically constructing and implementing such interfaces in Racket (define datatype lc-exp lc-exp? (var-exp (var identifier?)) (lambda-exp (bound-var identifier?) (body lc-exp?)) (app-exp (rator lc-exp?) (rand lc-exp?)))

  9. A Tool for Defining Recursive Data Types cont… This expression defines three constructors and one predicate. Which are those constructors and the predicate? In general, a define-datatype declaration has the form (define-datatype type-name type-predicate-name { (variant-name { (field-name predicate}*) }+ ) This creates a data type, named type-name, with some variants A record can be defined as a data type with a single variant. In that case, we name the constructor a-type-name or an-type-name

  10. A Tool for Defining Recursive Data Types cont… In place of various predicates and extractors, we use the form cases to determine the variant to which an object of data belongs, and to extract its information (define occurs-free? (lambda (search-var exp) (cases lc-exp exp (var-exp (var) (eqv? var search-var)) (lambda-exp (bound-var body) (and (not (eqv? search-var bound-var)) (occurs-free? search-var body))) (app-exp (rator rand) (or (occurs-free? search-var rator) (occurs-free? search-var rand))))))

  11. A Tool for Defining Recursive Data Types cont… The general syntax of cases is (cases type-name expression { (variant-name ( {field-name}* ) consequent) }* (else default)) The form specifies the type, the expression yielding the value to be examined, and a sequence of clauses Each clause is labeled with the name of a variant of the given type and the names of its fields The else clause is optional

  12. Abstract Syntax and its Representation A grammar usually specifies a particular representation of an inductive data type: one that uses the strings or values generated by the grammar. Such a representation is called concrete syntax, or external representation In order to process such data, we need to convert it to an internal representation. The define-datatype form provides a convenient way of defining such an internal representation. We call this abstract syntax What is abstract syntax and why is it needed? It is convenient to visualize the internal representation as an abstract syntax tree

  13. Abstract Syntax and its Representation cont… This is the abstract syntax tree for (lambda (x) (f (f x))) , using the data type lc-exp

  14. Abstract Syntax and its Representation cont… We can summarize the choices we have made in previous picture using the following concise notation: Lc-exp ::= Identifier ::= (lambda (Identifier) Lc-exp) ::= (Lc-exp Lc-exp)

  15. Abstract Syntax and its Representation cont… Having made the distinction between concrete syntax and abstract syntax, we now consider how to convert from one syntax to the other If the concrete syntax is a set of strings of characters, converting it to abstract syntax may be very difficult This task is called parsing and is performed by a parser Because writing parser is generally difficult, it is best performed by a took called parser generator

  16. Abstract Syntax and its Representation cont… If the concrete syntax is given as set of lists, the parsing process is considerably simplified For example, the following grammar for lambda-calculus expressions is given as set of lists. Lc-exp ::= Identifier ::= (lambda (Identifier) Lc-exp) ::= (Lc-exp Lc-exp) In this case, the Racket automatically parses strings into lists and symbols. It is then easier to parse these list structures into abstract syntax

  17. Parsing (define parse-expression (lambda (datum) (cond ((symbol? datum) (var-exp datum)) ((pair? datum) (if (eqv? (car datum) 'lambda) (lambda-exp (car (cadr datum)) (parse-expression (caddr datum))) (app-exp (parse-expression (car datum)) (parse-expression (cadr datum))))) (else (report-invalid-concrete-syntax datum)))))

  18. Unparsing It is usually straightforward to convert an abstract syntax back to a list and symbol representation (define unparse-lc-exp (lambda (exp) (cases lc-exp exp (var-exp (var) var) (lambda-exp (bound-var body) (list 'lambda (list bound-var) (unparse-lc-exp body))) (app-exp (rator rand) (list (unparse-lc-exp rator) (unparse-lc-exp rand))))))

  19. Practice1 Write a define-datatype for bintree Write parsing and unparsing for the grammar of bintree, using define-datatype (from question 1) and cases

  20. Practice1 - Solution (define-datatype bintree bintree? (leaf-node (num integer?)) (interior-node (key symbol?) (left bintree?) (right bintree?))) (define parsetree (lambda (datum) (if (btree? datum) (cond ((integer? datum) (leaf-node datum)) ((symbol? (car datum)) (interior-node (car datum) (parsetree (cadr datum)) (parsetree (caddr datum))))) (report-invalid-bintree datum))))

  21. Practice1 – Solution cont… (define unparsetree (lambda (btree) (cases bintree btree (leaf-node (num) num) (interior-node (key left right) (list key (unparsetree left) (unparsetree right)))))) (define btree? (lambda (bt) (or (integer? bt) (and (list? bt) (eqv? (length bt) 3) (symbol? (car bt)) (btree? (cadr bt)) (btree? (caddr bt))))))

More Related