41
Parsing Strategies Eric Roberts CS 106B March 6, 2013

Parsing Strategies

  • Upload
    ziva

  • View
    28

  • Download
    0

Embed Size (px)

DESCRIPTION

Parsing Strategies. Eric Roberts CS 106B March 6, 2013. Contest Results. The CS106B Recursion Contest March 2013. Recursion Contest Results. First place (algorithmic):. Dylan Moore , Connect Four. Runner-up (algorithmic):. Vineeth Gangaram , Heuristic Sudoku. - PowerPoint PPT Presentation

Citation preview

Page 1: Parsing Strategies

Parsing Strategies

Eric RobertsCS 106B

March 6, 2013

Page 2: Parsing Strategies

Contest Results

The CS106BRecursion ContestMarch 2013

Page 3: Parsing Strategies

Recursion Contest Results

First place (algorithmic): Dylan Moore, Connect FourRunner-up (algorithmic): Vineeth Gangaram, Heuristic SudokuRunner-up (algorithmic): Harry Simon, Sudoku Generator

First place (aesthetic): Matt Lathrop, Recursive Artist

Grand prize (both categories): Gio Jacuzzi, Kaleidoscope

Runner-up (aesthetic): Xiaolin Lin, L-SystemsRunner-up (aesthetic): Jed Paul, Camouflage Creator

Honorable mention: Brad Girardeau, The Game of LifeHonorable mention: Christina Lee, Because Everyone Loves Sudoku

Honorable mention: Thaminda Edirisooriya, Fractal Hero

Page 4: Parsing Strategies

The Problem of Parsing• The rules for forming an expression can be expressed in the

form of a grammar, as follows:

E constantE identifierE E op EE ( E )

• The process of translating an expression from a string to its internal form is called parsing.

Page 5: Parsing Strategies

A Two-Level Grammar• The problem of parsing an expression can be simplified by

changing the grammar to one that has two levels:– An expression is either a term or two expressions joined by an

operator.– A term is either a constant, an identifier, or an expression

enclosed in parentheses.• This design is reflected in the following revised grammar.

T constantT identifier

E E op E

T ( E )

E T

Page 6: Parsing Strategies

Ambiguity in Parse Structures• Although the two-level grammar from the preceding slide can

recognize any expression, it is ambiguous because the same input string can generate more than one parse tree.

x + 2 * y

T T T

E

E

x + 2 * y

TTT

E

E

• Ambiguity in grammars is typically resolved by providing the parser with information about the precedence of the operators. The text describes two strategies: Iversonian precedence, in which the operators all group to the right, and operator precedence, in which each operator is associated with an integer that defines its place in the precedence hierarchy.

Page 7: Parsing Strategies

Exercise: Parsing an Expression• Diagram the expression tree that results from the input string

2 * n + 1odd =

IDENTIFIERodd

CONSTANT

2

CONSTANT

1

IDENTIFIER

n

COMPOUND*

COMPOUND+

COMPOUND

=

Page 8: Parsing Strategies

/* * Implementation notes: readE * Usage: exp = readE(scanner, prec); * ---------------------------------- * This function reads the next expression from the scanner by * matching the input to the following ambiguous grammar: * * E -> T * E -> E op E * * This version of the method uses precedence to resolve ambiguity. */

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;}

The parser.cpp Implementation

Page 9: Parsing Strategies

/* * Implementation notes: readE * Usage: exp = readE(scanner, prec); * ---------------------------------- * This function reads the next expression from the scanner by * matching the input to the following ambiguous grammar: * * E -> T * E -> E op E * * This version of the method uses precedence to resolve ambiguity. */

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;}

/* * Function: readT * Usage: exp = readT(scanner); * ---------------------------- * This function reads a single term from the scanner. */

Expression *readT(TokenScanner & scanner) { string token = scanner.nextToken(); TokenType type = scanner.getTokenType(token); if (type == WORD) return new IdentifierExp(token); if (type == NUMBER) return new ConstantExp(stringToInteger(token)); if (token != "(") error("Illegal term in expression"); Expression *exp = readE(scanner, 0); if (scanner.nextToken() != ")") { error("Unbalanced parentheses in expression"); } return exp;}

The parser.cpp Implementation

Page 10: Parsing Strategies

/* * Function: readT * Usage: exp = readT(scanner); * ---------------------------- * This function reads a single term from the scanner. */

Expression *readT(TokenScanner & scanner) { string token = scanner.nextToken(); TokenType type = scanner.getTokenType(token); if (type == WORD) return new IdentifierExp(token); if (type == NUMBER) return new ConstantExp(stringToInteger(token)); if (token != "(") error("Illegal term in expression"); Expression *exp = readE(scanner, 0); if (scanner.nextToken() != ")") { error("Unbalanced parentheses in expression"); } return exp;}

/* * Function: precedence * Usage: prec = precedence(token); * -------------------------------- * This function returns the precedence of the specified operator * token. If the token is not an operator, precedence returns 0. */

int precedence(string token) { if (token == "=") return 1; if (token == "+" || token == "-") return 2; if (token == "*" || token == "/") return 3; return 0;}

The parser.cpp Implementation

Page 11: Parsing Strategies

Tracing the Precedence Parser

skip simulation

int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); scanner.scanNumbers(); Expression *exp = readE(scanner, 0); . . .}

scanner expodd = 2 * n + 1^

Page 12: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); scanner.scanNumbers(); Expression *exp = readE(scanner, 0); . . .}

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1^ 0

Page 13: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); Expression *exp = readE(scanner, 0); . . .}

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1^ 0

Expression *readT(TokenScanner & scanner) { string token = scanner.nextToken(); TokenType type = scanner.getTokenType(token); if (type == WORD) return new IdentifierExp(token); if (type == NUMBER) return new ConstantExp(stringToInteger(token)); if (token != "(") error("Illegal term in expression"); Expression *exp = readE(scanner, 0); if (scanner.nextToken() != ")") { error("Unbalanced parentheses in expression"); } return exp;} scanner token exptype

odd = 2 * n + 1^ ^ oddWORD

Page 14: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); Expression *exp = readE(scanner, 0); . . .}

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 0

Expression *readT(TokenScanner & scanner) { string token = scanner.nextToken(); TokenType type = scanner.getTokenType(token); if (type == WORD) return new IdentifierExp(token); if (type == NUMBER) return new ConstantExp(stringToInteger(token)); if (token != "(") error("Illegal term in expression"); Expression *exp = readE(scanner, 0); if (scanner.nextToken() != ")") { error("Unbalanced parentheses in expression"); } return exp;} scanner token exptype

Page 15: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); Expression *exp = readE(scanner, 0); . . .}

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1^ 0

oddID

^ =1

Page 16: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); Expression *exp = readE(scanner, 0); . . .}

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 0

oddID

^ =1

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1^ 1

Page 17: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); Expression *exp = readE(scanner, 0); . . .}

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1^ 0

oddID

^ =1

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1^ 1

Expression *readT(TokenScanner & scanner) { string token = scanner.nextToken(); TokenType type = scanner.getTokenType(token); if (type == WORD) return new IdentifierExp(token); if (type == NUMBER) return new ConstantExp(stringToInteger(token)); if (token != "(") error("Illegal term in expression"); Expression *exp = readE(scanner, 0); if (scanner.nextToken() != ")") { error("Unbalanced parentheses in expression"); } return exp;} scanner token exptype

odd = 2 * n + 1^ ^ 2NUMBER

Page 18: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); Expression *exp = readE(scanner, 0); . . .}

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1^ 0

oddID

^ =1

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1^ 1

Expression *readT(TokenScanner & scanner) { string token = scanner.nextToken(); TokenType type = scanner.getTokenType(token); if (type == WORD) return new IdentifierExp(token); if (type == NUMBER) return new ConstantExp(stringToInteger(token)); if (token != "(") error("Illegal term in expression"); Expression *exp = readE(scanner, 0); if (scanner.nextToken() != ")") { error("Unbalanced parentheses in expression"); } return exp;} scanner token exptype

Page 19: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); Expression *exp = readE(scanner, 0); . . .}

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 0

oddID

^ =1

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1^ 1

2CONST

^ 3 *

Page 20: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); Expression *exp = readE(scanner, 0); . . .}

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1

oddID

^ =

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 1

2CONST

^ 3 *=

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1^ 3

Page 21: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); Expression *exp = readE(scanner, 0); . . .}

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 0

oddID

^ =1

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 1

2CONST

^ 2 *odd = 2 * n + 1 0 =1

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1^ 3

Expression *readT(TokenScanner & scanner) { string token = scanner.nextToken(); TokenType type = scanner.getTokenType(token); if (type == WORD) return new IdentifierExp(token); if (type == NUMBER) return new ConstantExp(stringToInteger(token)); if (token != "(") error("Illegal term in expression"); Expression *exp = readE(scanner, 0); if (scanner.nextToken() != ")") { error("Unbalanced parentheses in expression"); } return exp;} scanner token exptype

odd = 2 * n + 1^ ^ nWORD

Page 22: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); Expression *exp = readE(scanner, 0); . . .}

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 0

oddID

^ =1

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 1

2CONST

^ 2 *odd = 2 * n + 1 0 =1

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1^ 3

Expression *readT(TokenScanner & scanner) { string token = scanner.nextToken(); TokenType type = scanner.getTokenType(token); if (type == WORD) return new IdentifierExp(token); if (type == NUMBER) return new ConstantExp(stringToInteger(token)); if (token != "(") error("Illegal term in expression"); Expression *exp = readE(scanner, 0); if (scanner.nextToken() != ")") { error("Unbalanced parentheses in expression"); } return exp;} scanner token exptype

Page 23: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); Expression *exp = readE(scanner, 0); . . .}

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

oddID

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

2CONST

2 *odd = 2 * n + 1 0 =1

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1^ 3

nID

^ 2 +

Page 24: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); Expression *exp = readE(scanner, 0); . . .}

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

oddID

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

2CONST

3odd = 2 * n + 1 0

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

nID

Page 25: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); Expression *exp = readE(scanner, 0); . . .}

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 0

oddID

^ =1

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1^ 1

2CONST

^ 3 *

nID

*COMP

2 +

Page 26: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); Expression *exp = readE(scanner, 0); . . .}

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 0

oddID

^ =1

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 1

2CONST

^ 3 *

nID

*COMP

2 +

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1^ 2

Page 27: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); Expression *exp = readE(scanner, 0); . . .}

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 0

oddID

^ =1

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 1

2CONST

^ 3 *

nID

*COMP

2 +

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1^ 2

Expression *readT(TokenScanner & scanner) { string token = scanner.nextToken(); TokenType type = scanner.getTokenType(token); if (type == WORD) return new IdentifierExp(token); if (type == NUMBER) return new ConstantExp(stringToInteger(token)); if (token != "(") error("Illegal term in expression"); Expression *exp = readE(scanner, 0); if (scanner.nextToken() != ")") { error("Unbalanced parentheses in expression"); } return exp;} scanner token exptype

odd = 2 * n + 1^ ^ 1NUMBER

Page 28: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); Expression *exp = readE(scanner, 0); . . .}

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 0

oddID

^ =1

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 1

2CONST

^ 3 *

nID

*COMP

2 +

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1^ 2

1CONST

Expression *readT(TokenScanner & scanner) { string token = scanner.nextToken(); TokenType type = scanner.getTokenType(token); if (type == WORD) return new IdentifierExp(token); if (type == NUMBER) return new ConstantExp(stringToInteger(token)); if (token != "(") error("Illegal term in expression"); Expression *exp = readE(scanner, 0); if (scanner.nextToken() != ")") { error("Unbalanced parentheses in expression"); } return exp;} scanner token exptype

Page 29: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); Expression *exp = readE(scanner, 0); . . .}

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 0

oddID

^ =1

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 1

2CONST

^ 3 *

nID

*COMP

2 +

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1̂ 2

1CONST

0

Page 30: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); Expression *exp = readE(scanner, 0); . . .}

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 0

oddID

^ =1

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 1

2CONST

^ 3 *

nID

*COMP

2 +

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

1CONST

Page 31: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); Expression *exp = readE(scanner, 0); . . .}

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 0

oddID

^ =1

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 1

2CONST

^ 2 +

nID

*COMP

0

1CONST

+COMP

Page 32: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); Expression *exp = readE(scanner, 0); . . .}

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 0

oddID

^ =1

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

2CONST

nID

*COMP

1CONST

+COMP

Page 33: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); Expression *exp = readE(scanner, 0); . . .}

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

odd = 2 * n + 1 0

oddID

^ =1

2CONST

nID

*COMP

1CONST

+COMP

0

=COMP

Page 34: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); scanner.scanNumbers(); Expression *exp = readE(scanner, 0); . . .}

scanner expodd = 2 * n + 1^

Expression *readE(TokenScanner & scanner, int prec) { Expression *exp = readT(scanner); string token; while (true) { token = scanner.nextToken(); int tprec = precedence(token); if (tprec <= prec) break; Expression *rhs = readE(scanner, tprec); exp = new CompoundExp(token, exp, rhs); } scanner.saveToken(token); return exp;} scanner prec tprec token exp rhs

oddID

2CONST

nID

*COMP

1CONST

+COMP

=COMP

Page 35: Parsing Strategies

Tracing the Precedence Parser int main() { TokenScanner scanner = new TokenScanner(); scanner.setInput("odd = 2 * n + 1"); scanner.ignoreWhitespace(); scanner.scanNumbers(); Expression *exp = readE(scanner, 0); . . .}

oddID

2CONST

nID

*COMP

1CONST

+COMP

=COMP

scanner expodd = 2 * n + 1^

Page 36: Parsing Strategies
Page 37: Parsing Strategies

Exercise: Coding a BASIC Program• On the second practice midterm, one of the problems

concerned the hailstone sequence. For any positive integer n, you compute the terms in the hailstone sequence by repeatedly executing the following steps:– If n is equal to 1, you’ve reached the end of the sequence and can stop.– If n is even, divide it by two.– If n is odd, multiply it by three and add one.

• Write a BASIC program that reads in an integer and prints out its hailstone sequence.

Page 38: Parsing Strategies

The Basic Starter Project

Page 39: Parsing Strategies

Modules in the Starter FolderBasic.cpp You write this one, but it’s short.

exp.hexp.cpp

You need to remove the = operator and add a few things to EvaluationContext.

parser.hparser.cpp

You need to remove the = operator.

program.hprogram.cpp

You’re given the interface, but need to write the private section and the implementation.

statement.hstatement.cpp

You’re given the interface and need to supply the implementation.

Page 40: Parsing Strategies

Your Primary TasksFigure out how the pieces of the program go together and what you need to do.

1.

Code the Program class, keeping in mind what methods need to run in constant time.

2.

Implement the Statement class hierarchy: 3.

Page 41: Parsing Strategies

The End