CSCE 434 Lecture 16
« previous | Monday, September 30, 2013 | next »
Tangent: Recursive Programs
Speed: Recursion is not usually fast.
- Create stack frame
- push arguments onto stack
- execute function call
- pop stack
Some compilers convert them to loops instead of recursion.
Optimizing a for-loop is easier than a while-loop because a for-loop is bounded. (something about GPUs) Both are difficult, but an unbounded while-loop is harder.
Predictive parsing
- tables built from specification
- state stack
- parser reads from tables; process is an implementation of a finite state machine
LL(1) Parse Algorithm
int tos = 0;
stack[tos++] = eof;
stack[tos++] = start_symbol;
Token token = next_token();
Token X = Stack[tos];
do {
if (X is a terminal || X == eof) {
if (X == Token) {
pop X;
token = next_token();
} else error();
} else { // X is a non-terminal
if (M[X,token] == "X ::= { Y[1], Y[2], ..., Y[k] }")
pop X;
push Y[k], Y[k-1], ..., Y[1]
} else error()
}
X = stack[tos];
} while (X != eof)
LL(1) Table for our grammar
id | num | + | - | * | / | eof | |
---|---|---|---|---|---|---|---|
<goal> | <g> ::= <e> | <g> ::= <e> | |||||
<expr> | <e> ::= <t> <e'> | <e> ::= <t> <e'> | |||||
<expr'> | <e'> ::= + <t> <e'> | <e'> ::= - <t> <e'> | <e'> ::= ε | ||||
<term> | <t> ::= <f> <t'> | <t> ::= <f> <t'> | |||||
<term'> | <t'> ::= ε | <t'> ::= ε | <t'> ::= * <f> <t'> | <t'> ::= / <f> <t'> | <t'> ::= ε | ||
<factor> | <f> ::= id | <f> ::= num |
First Set
is the set of terminal symbols that begin strings derived from α
If , then .
Building :
- If is a terminal, .
- If , then
- If , then put in
- If is a non-terminal and , then if and for (keep looking at the next until we get one that can't go to )
Follow Set
For nonterminal , define as the set of terminals that can appear immediately to the right of in some sentential form.
Thus a non-terminal's follow set specifies the tokens that can legally appear after it
A terminal symbol has now follow set.
To build:
- If , then put in . We don't know enough about , but this rule tells us something about .
- If , then put in
- If and , then put in (almost the same thing as above; if nothing follows , then anything that follows can follow by this rule)
Constructing a Parse Table
- For any production , perform steps 2–4
- for any terminal a in first(\alpha), add to
- If , add to for all terminals .
- If and , add to .
- Set each undefined entry of to error
If this fails, the grammar is not LL(1), so we can make it LL(1) by adding non-terminals:
LL(1) Grammars
A grammar is LL(1) if and only if for all non-terminals , teach distinct pair of productions and satisfy the following condition: .
Properties:
- no left-recursive grammar is LL(1)
- no ambiguous grammar is LL(1)
- LL(1) parsers operate in linear time
- epsilon-free grammar , where each alternative expansion for begins with a distinct terminal is a simple LL(1) grammar.