CSCE 434 Lecture 22
« previous | Monday, October 14, 2013 | next »
Choose optimization project for pp6
preferably something about data flow
Associativity and Precedence
Used to resolve shift/reduce conflicts in ambiguous grammars
- Lookahead with higher precedence: shift
 - Same precedence, left associative: reduce
 
Allows for:
- more concise, albeit ambiguous grammars
 - Shallower parse trees (fewer reductions)
 
Simple expression grammar:
<expr> ::= <expr> * <expr>
         | <expr> / <expr>
         | <expr> + <expr>
         | <expr> - <expr>
         | ( <expr> )
         | - <expr>
         | id
         | num
         ;
Error Recovery
Synchronizing terminals (for each nonterminal): When an error occurs when looking for nonterminal , scan until an element of is found, then pop and continue.
Building:
- If , then
 - Place keywords that start statements in
 
Problem: if we encounter an invalid token, we'll have bad pieces of tree hanging from the stack and incorrect entries in the symbol table.
- We need to find a state in which we can restart our parsing
 - Move to consistent place in input
 - Print an informative error message
 
Yacc/Bison
Special error token
invoke yyerror(char*)
Augmented grammar is LR(1) if the following 3 conditions:
imply that (i.e. , , and )
LR(k) Items
Lookahead consists of strings of length .
Items are like LR(0) items, but have additional lookahead:
Augmented start rule item is
Context-Sensitive Analysis
Context: implicit or explicit declarations, scope
Answers questions like:
- Is an expression type-consistent?
 - Does the dimension of a reference match its declaration?
 - Where can x be stored? (stack, heap, memory*, etc.)
 - Is x declared before it is used?
 
why is context-sensitive analysis hard?
- Need access to non-local information
 - Answers depend on values, not syntax
 - Answers may involve computation
 
Approaches to solve above problems:
- Write context-sensitive grammars (computationally hard)
 - ad-hoc techniques (symbol tables and code; yacc "action routines"; this is what we use)
 - formal methods (syntax-directed translation; type systems, checking algorithms)
 
Attribute Grammars
Decorate the tree
- Add attributes (fields) to each node
 - specify equations to define values
 - Inherited (on parent) and synthesized (on self) attributes
 
- Add type and class attributes on expressions
 - For example, assignment checks that LHS is a variable and that the LHS/RHS types are consistent or conformable [1]
 
Footnotes
- ↑ Conformable means that the dimensions/size of the types are the same