1.43k likes | 1.77k Views
Review. Lexical Analysis Syntax Analysis Semantic Analysis Code Generation Code Optimization. Syntax Analysis. Often called parsing Groups tokens of source program into grammatical phrases that are used by the compiler to check for correct syntax and to help in generating code
E N D
Review • Lexical Analysis • Syntax Analysis • Semantic Analysis • Code Generation • Code Optimization
Syntax Analysis • Often called parsing • Groups tokens of source program into grammatical phrases that are used by the compiler to check for correct syntax and to help in generating code • Creation of a hierarchical structure called a syntax tree • Tree helps us determine if program is syntactically correct • Also aids in the translation of source program to target language
Seattle San Francisco Grammar Example • Lexical • Ogay orthnay eightay undrendhay ilesmay • Syntactical • Miles go hundred north eight • Logical • Go eight hundred miles(facing south) • Run-Time • Go eight hundred miles (facing West)
Grammars – Defining the Language Rules • Terminals (tokens) • Non-terminals - Syntactic variable. Contains groups of tokens that define some part of the language • Example: expression, if statement, etc • Start symbol - A special non-terminal (i.e. a program) • Productions • The manner in which terminals and non-terminals are combined to form statements • A non-terminal in LHS and a string of terminals and non-terminals in RHS
Example • Variable Declaration • A type followed by one or more comma separated identifiers that end with a semi-colon. <Var> -> <Indent> <Var> -> <Var> , <Ident> • <Var> and <Ident> are non-terminals • The comma is a terminal • The two lines are called productions
Grammars • We will be defining a grammar for the entire JO99 programming language. • We will then have JCUP produce for us a parser that detects if the JO99 program is syntactically correct. • In addition, the parser will create for us a tree that represents the program and allows us to be able to do other things like semantic checks and code generation.
Example • Simple arithmetic expressions with + and * • 8.2 + 35.6 • 8.32 + 86 * 45.3 • (6.001 + 6.004) * (6.035 * -(6.042 + 6.046)) • Terminals (or tokens) • num for all the numbers • ‘+’, ‘-’, ‘*’, ‘(‘, ‘)’ • What is the grammar for all possible expressions?
Example <expr> <expr> <op> <expr> <expr> ( <expr> ) <expr> - <expr> <expr> num <op> + <op> *
Categories of Parsers • L - parse from left to right • R - parse from right to left ( )
Categories of Parsers • L - leftmost derivation • R - rightmost derivation ( )
Categories of Parsers • Number of look ahead characters ( )
Categories of Parsers • Examples: • LL(0) – Parse Left to Right, Derive the tree using a leftmost derivation (top down), no look ahead characters • LR(1) – Parse Left to Right, Derive the tree using a rightmost derivation (bottom up), 1 look ahead character. • Each category of parsing handles a different type of language. • We will be learning about LR(k) parsers and will implement an LR(k) parser.
Why LR(k)? • Virtually all programming language grammars can be parsed using a LR(k) technique • Most general parsing method for programming grammars • Can build a very efficient parser engine given just the syntax rules of the language. • Can detect a syntactic error as soon as it is possible to do so • Because its so general, programs have been written (JCUP) that produce the parser instead of writing it from scratch.
LR(k) Parser implementation • Sometimes called a Shift-Reduce Parser • Parse from left to right (get the tokens from left to right) • Bottom up parsing (same as rightmost derivation)
Actions of a Shift-Reduce Parser Parse Tree
Actions of a Shift-Reduce Parser Parse Tree Parse Tree
Actions of a Shift-Reduce Parser Parse Tree Parse Tree
Actions of a Shift-Reduce Parser Parse Tree Parse Tree
Actions of a Shift-Reduce Parser Parse Tree Parse Tree
Actions of a Shift-Reduce Parser Parse Tree Parse Tree
Actions of a Shift-Reduce Parser Parse Tree Parse Tree
Actions of a Shift-Reduce Parser Parse Tree Parse Tree
Actions of a Shift-Reduce Parser Parse Tree
Actions of a Shift-Reduce Parser Parse Tree
Actions of a Shift-Reduce Parser Parse Tree
Actions of a Shift-Reduce Parser Parse Tree
Actions of a Shift-Reduce Parser • How do we build this tree? • As productions are recognized, a portion of the tree is created. • This portion of the tree will be needed later to build bigger portions of the tree and therefore must be saved for future use. • This requires a stack. • The stack plus the next token read from the source program determines the action.
Parser Engine Actions of a Shift-Reduce Parser stack Parser Action Stack Current Symbol
Actions of a Shift-Reduce Parser • Shift • Shift the current element into top of the stack • Move the current pointer (next token) • Reduce • Apply a production (we recognize a part of the program) • Top of the stack should match the RHS of the grammar • Remove those symbols from the stack • Add the LHS non-terminal • Accept • End of stream reached and stack only has the start symbol • Reject • End of stream reached but stack has more than the start symbol
Shift-Reduce Parser Example num * ( num + num )
Shift-Reduce Parser Example <expr> <expr> <op> <expr> <expr> ( <expr> ) <expr> - <expr> <expr> num <op> + <op> - <op> * num * ( num + num )
Shift-Reduce Parser Example <expr> <expr> <op> <expr> <expr> ( <expr> ) <expr> - <expr> <expr> num <op> + <op> - <op> * num * ( num + num )
Shift-Reduce Parser Example <expr> <expr> <op> <expr> <expr> ( <expr> ) <expr> - <expr> <expr> num <op> + <op> - <op> * num SHIFT num * ( num + num )
Shift-Reduce Parser Example <expr> <expr> <op> <expr> <expr> ( <expr> ) <expr> - <expr> <expr> num <op> + <op> - <op> * num REDUCE num * ( num + num )
Shift-Reduce Parser Example <expr> <expr> <op> <expr> <expr> ( <expr> ) <expr> - <expr> <expr> num <op> + <op> - <op> * <expr> <expr> <expr> <expr> REDUCE <expr> <op> <expr> <op> <expr> num * ( num + num )
Shift-Reduce Parser Example <expr> <expr> <op> <expr> <expr> ( <expr> ) <expr> - <expr> <expr> num <op> + <op> - <op> * <expr> <expr> * <expr> <expr> SHIFT <expr> <op> <expr> <op> <expr> num * ( num + num )
Shift-Reduce Parser Example <expr> <expr> <op> <expr> <expr> ( <expr> ) <expr> - <expr> <expr> num <op> + <op> - <op> * <expr> <expr> * <expr> <expr> REDUCE <expr> <op> <expr> <op> <expr> num * ( num + num )
Shift-Reduce Parser Example <expr> <expr> <op> <expr> <expr> ( <expr> ) <expr> - <expr> <expr> num <op> + <op> - <op> * <expr> <expr> <op> <expr> <expr> REDUCE <expr> <op> <expr> <op> <expr> num * ( num + num )
Shift-Reduce Parser Example <expr> <expr> <op> <expr> <expr> ( <expr> ) <expr> - <expr> <expr> num <op> + <op> - <op> * <expr> ( <expr> <op> <expr> <expr> SHIFT <expr> <op> <expr> <op> <expr> num * ( num + num )
Shift-Reduce Parser Example <expr> <expr> <op> <expr> <expr> ( <expr> ) <expr> - <expr> <expr> num <op> + <op> - <op> * <expr> num ( <expr> <op> <expr> <expr> SHIFT <expr> <op> <expr> <op> <expr> num * ( num + num )
Shift-Reduce Parser Example <expr> <expr> <op> <expr> <expr> ( <expr> ) <expr> - <expr> <expr> num <op> + <op> - <op> * <expr> num ( <expr> <op> <expr> <expr> REDUCE <expr> <op> <expr> <op> <expr> num * ( num + num )
Shift-Reduce Parser Example <expr> <expr> <op> <expr> <expr> ( <expr> ) <expr> - <expr> <expr> num <op> + <op> - <op> * <expr> <expr> ( <expr> <op> <expr> <expr> REDUCE <expr> <op> <expr> <op> <expr> num * ( num + num )
Shift-Reduce Parser Example <expr> <expr> <op> <expr> <expr> ( <expr> ) <expr> - <expr> <expr> num <op> + <op> - <op> * + <expr> <expr> ( <expr> <op> <expr> <expr> SHIFT <expr> <op> <expr> <op> <expr> num * ( num + num )
Shift-Reduce Parser Example <expr> <expr> <op> <expr> <expr> ( <expr> ) <expr> - <expr> <expr> num <op> + <op> - <op> * + <expr> <expr> ( <expr> <op> <expr> <expr> REDUCE <expr> <op> <expr> <op> <expr> num * ( num + num )
Shift-Reduce Parser Example <expr> <expr> <op> <expr> <expr> ( <expr> ) <expr> - <expr> <expr> num <op> + <op> - <op> * <op> <expr> <expr> ( <expr> <op> <expr> <expr> REDUCE <expr> <op> <expr> <op> <expr> num * ( num + num )
Shift-Reduce Parser Example <expr> <expr> <op> <expr> <expr> ( <expr> ) <expr> - <expr> <expr> num <op> + <op> - <op> * num <op> <expr> <expr> ( <expr> <op> <expr> <expr> SHIFT <expr> <op> <expr> <op> <expr> num * ( num + num )
Shift-Reduce Parser Example <expr> <expr> <op> <expr> <expr> ( <expr> ) <expr> - <expr> <expr> num <op> + <op> - <op> * num <op> <expr> <expr> ( <expr> <op> <expr> <expr> REDUCE <expr> <op> <expr> <op> <expr> num * ( num + num )
Shift-Reduce Parser Example <expr> <expr> <op> <expr> <expr> ( <expr> ) <expr> - <expr> <expr> num <op> + <op> - <op> * <expr> <op> <expr> <expr> ( <expr> <op> <expr> <expr> REDUCE <expr> <op> <expr> <op> <expr> num * ( num + num )
Shift-Reduce Parser Example <expr> <expr> <op> <expr> <expr> ( <expr> ) <expr> - <expr> <expr> num <op> + <op> - <op> * <expr> <op> <expr> <expr> ( <expr> <op> <expr> <expr> REDUCE <expr> <op> <expr> <op> <expr> num * ( num + num )