130 likes | 332 Views
Discussion #7 Recursive Descent Parsing. Topics. Recursive Descent Parsing Use tables to build recursive descent parsers Parse tree construction Project #2 Parsing. Recursive Descent Parsing. Consider an arbitrary production S xAySz
E N D
Topics • Recursive Descent Parsing • Use tables to build recursive descent parsers • Parse tree construction • Project #2 Parsing
Recursive Descent Parsing • Consider an arbitrary production S xAySz and assume x is the current (top symbol), i.e.: x S (xAySz, …)
Recursive Descent Parsing (continued…) • Make a method for S (indeed, for every non-terminal) as follows: • For S xAySz • Attempt to read an x from the input. • If success, call method A. • If success, attempt to read a y from the input. • If success call method S. • If success attempt to read a z from the input. • If success, method S reports success! • If any of the above attempts fail, report failure.
Recursive Descent Parsing (continued…) • Make a method for S (indeed, for every non-terminal) as follows: • For S xAySz | q • If x is the current input character then • call method A. • If success, attempt to read a y from the input. • If success call method S. • If success attempt to read a z from the input. • If success, method S reports success! • Else if q is the current input character then, report success • Else report error
E O E E Recursive Descent Parsing (continued…) • Output from each syntactical class is a left-child, right-sibling parse tree. • E OEE produces:
Recursive Descent Parsing Example • Consider our prefix grammar: E N | OEEO + | | * | / N 0 | 1 | … | 9 • Design a series of recursive methods: • E() to process N or O, E, E • O() to process +, , *, / • N() to process numbers 0 thru 9
Data Structure for Parse Tree class parseTree { … char value parseTree leftChild parseTree rightSibling … };
Initialization: Call to Start Symbol parseTree buildTree() // build parse tree { … nextChar = readChar() // read 1st character ptree = E() // start syntactic class if (ptree == error) return error if (nextChar) return error // check for string finished return ptree // return the full parse tree }
Method for E parseTree E() // syntactic category E { parseTree ptree,sibling1,sibling2 if (isCharInString(nextChar, "+-*/")) // E -> OEE {FIRST(OEE)} { ptree = O() // Try to recognize O if (ptree == error) return error sibling1 = E() // Try to recognize E if (sibling1 == error) return error sibling2 = E() // Try to recognize E if (sibling2 == error) return error ptree.rightSibling = sibling1 // Success, link O->E->E ptree.rightSibling.rightSibling = sibling2 } else if (isCharInString(nextChar, "0123456789")) // E -> N { ptree = N() // Try to recognize N if (ptree == error) return error } else return error return new parseTree('E', ptree, null) }
Methods for N and O parseTree N() // syntactic category N { ptree = new parseTree(nextChar, null, null) nextChar = readChar() return new parseTree('N', ptree, null) } parseTree O() // syntactic category O { ptree = new parseTree(nextChar, null, null) nextChar = readChar() return new parseTree('O', ptree, null) }
Recursive Descent Parser Execution for +*-748/92 E O E E * N N + * - 7 4 8 / 9 2 2 3
ConstructingRecursive Descent Parsers • Can be applied to almost all grammars. • Required property: By looking at the look-ahead symbol, we know which production to process next. • Grammars with this single-symbol look-ahead property are called single-symbol look-ahead grammars. • Alternatives: • Backtracking • LR(k) k symbol look ahead • Make grammar have single-symbol look ahead.