Datateknik LTH

Visa påGitHub

Kurser / EDAN65-compilers / summary

Summary

Ambiguous grammars

Introduce new non-terminals to mitigate the ambiguity.

Ambiguous: Expr -> Expr "+" Expr Expr -> Expr "*" Expr Expr -> INT Expr -> "(" Expr ")" To make unambiguous, introduce new non terminals for each ambiguity. I.e. one for a member of the addition and one for the multiplication. The above in an unambiguous way becomes:

Expr    -> Term   ("+" Term)*
Term    -> Factor ("*" Factor)*
Factor  -> INT | "(" Expr ")"

One thing to remember is that the factor now has the highest precedence, then the term, then the expression.

Computing nullable, FIRST, FOLLOW

  • A non-terminal is nullable if it contains the epsilon production.
  • FIRST is a set of the first terminals in the productions for the non-terminal.
  • FOLLOW is the set of terminals that can follow the non-terminal production.

Constructing an LL(1) table

To construct the table, look at each production and compute the token set FIRST then add the production p_i under the terminals.

If the non-terminal is nullable, then compute the FOLLOW set and add the productions under those terminals.

Example:

p1: S -> T $
p2: T -> ID
p3: T -> "(" L ")"
p4: L ->  T R
p5: R -> "," L
p6: R -> epsilon
 _______________________________________________________
| Nonterminal | Nullable | FIRST        | FOLLOW        |
 -------------------------------------------------------
|     S       |  false   | { ID, "(" }  |               |
|     T       |  false   | { ID, "(" }  | { $, "," }    |
|     L       |  false   | { ID, "(" }  | { ")" }       |
|     R       |  true    | { "," }      | { ")" }       |
 -------------------------------------------------------
 ______________________________
|   | ID | "(" | ")" | "," | $ |
 ------------------------------
| S | p1 | p1  |     |     |   |
| T | p2 | p3  |     |     |   |
| L | p4 | p4  |     |     |   |
| R |    |     | p6  | p5  |   |
 ------------------------------

Removing common prefixes

In the following example the Element productions share an indirect common prefix

Graph       -> ElementList
ElementList -> Element ElementList
ElementList -> epsilon
Element     -> Node
Element     -> Edge
Node        -> ID
Edge        -> ID "(" ID "->" ID ")"

To eliminate the common prefix we have to get rid of Node and Edge's sharing of ID as the first terminal. This is done like so:

Graph       -> ElementList
ElementList -> Element ElementList
ElementList -> epsilon
Element     -> ID ElementRest
ElementRest -> "(" ID "->" ID ")"
ElementRest -> epsilon

The conflicting productions are merged.

Collection attributes

coll T A.c() [new T()] with m;
  • Where T is the type
  • A.c() is the location attribute
  • [new T()] is a fresh object of type T
  • m is the collection method which should be a one argument method in T

Contribution attributes

B contributes T to A.c() for A-ref
  • Where B is the contributing node
  • T is the value contributed to the collection method
  • A.c() is the collection attribute
  • A-ref is a reference to A. This can be propagated down via an inherited method