Title: Recursive descent parsing
1Recursive descent parsing
2The Stack
- One easy way to do recursive descent parsing is
to have each parse method take the tokens it
needs, build a parse tree, and put the parse tree
on a global stack - Write a parse method for each nonterminal in the
grammar - Each parse method should get the tokens it needs,
and only those tokens - Those tokens (usually) go on the stack
- Each parse method may call other parse methods,
and expect those methods to leave their results
on the stack - Each (successful) parse method should leave one
result on the stack
3Example while statement
- ltwhile statementgt while ltconditiongt ltblockgt
- The parse method for a ltwhile statementgt does
this - Calls the Tokenizer, which returns a while
token - Makes the while into a Tree, which it puts on
the stack - Calls the parser for ltconditiongt, which parses a
condition and puts a Tree representation of that
condition on the stack - Stack now contains while ltconditiongt (stack
top is on the right), where ltconditiongt stands
for some created Tree - Calls the parser for ltblockgt, which parses a
block and puts a Tree representation of that
block on the stack - Stack now contains while ltconditiongt
ltblockgt - Pops the top three things from the stack,
assembles them into a Tree representing a while
statement, and pushes this Tree onto the stack
4Sample Java code
- public boolean whileCommand() if
(keyword("while")) if (condition())
if (block())
makeTree(3, 2, 1) return true
error("Error in
\"while\" statement") return false
5makeTree
private void makeTree(int rootIndex, int...
childIndices) // Get root from stack
TreeltTokengt root getStackItem(rootIndex)
// Get other trees from stack and add them
as children of root for (int i 0 i lt
childIndices.length i)
root.addChild(getStackItem(childIndicesi))
// Pop root and all children from
stack for (int i 0 i lt
childIndices.length i)
stack.pop() // Put the root
back on the stack stack.push(root)
6getStackItem
private TreeltTokengt getStackItem(int n)
return stack.get(stack.size() - n)
7Fancier error messages
- public boolean whileCommand() if
(keyword("while")) if (condition())
if (block())
makeTree(3, 2, 1) // or some such
return true
error("Error in \"while\" block")
error("Error in \"while\" condition")
return false
8Alternative code
- public boolean whileCommand() if
(keyword("while") condition()
block()) makeTree(3, 2, 1) // or some
such return true return
false - No room for an error condition in this code
9Alternative code with one message
- public boolean whileCommand() if
(keyword("while")) if (condition())
(block()) makeTree(3, 2, 1) //
or some such return true
error("Error in \"while\" statement")
return false
10My isCommand() method
- public boolean command() if
(isAction()) return true if
(isRepeatStatement()) return true if
(isWhileStatement()) return true ...
11My helper methods
- I wrote a number of helper methods for the Parser
and for the ParserTest classes - One very useful method is tree, in the ParserTest
class - tree just takes Objects and builds a tree from
them - This method lets me build parse trees for use in
assertEquals tests - Another is assertStackTop, which is just
- private void assertStackTop(Tree bt)
assertEquals(bt, parser.stack.peek()) - Examples
- Tree condition tree("", "2", "2")
- assertStackTop(tree("if", condition, "list"))
12The End