120 likes | 466 Views
Recursive descent parsing. The 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
E N D
The 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
Example: if statement • <if statement> ::= “if” <condition> <block> • The parse method for an if statement: • Calls the Tokenizer, which returns an “if” token • Makes the “if” into a binary tree, which it puts on the stack • Calls the parser for <condition>, which parses a command and puts it on the stack • Stack now contains: “if” <condition> (“top” is on right) • Calls the parser for <block>, which parses a block and puts it on the stack • Stack now contains: “if” <condition> <block> • Pops the top three things from the stack, assembles them into a tree, and pushes this tree onto the stack
Sample Java code • public boolean ifCommand() { if (keyword("if")) { if (condition()) { if (block()) { makeTree(3, 2, 1); return true; } } error("Error in \"if\" statement"); } return false;}
Fancier error messages • public boolean ifCommand() { if (keyword("if")) { if (condition()) { if (block()) { makeTree(3, 2, 1); return true; } error("Error in \"if\" block"); } error("Error in \"if\" condition"); } return false;}
Alternative code • public boolean ifCommand() { if (keyword("if") && condition() && block()) { makeTree(3, 2, 1); return true; } return false;} • No room for an error condition in this code
Alternative code with one message • public boolean ifCommand() { if (keyword("if")) { if (condition()) && (block()) { makeTree(3, 2, 1); return true; } error("Error in \"if\" statement"); } return false;}
Parser methods • In the BNF, I have one long definition for <command> • <command> ::= <move> <expression> <eol> | "penup" <eol> | "pendown" <eol> | "color" <colorname> <eol> ... • In my code, I broke that into multiple methods • <command> ::= <move command> | <penup command> | <pendown command> | <color command> ...
My command() method • public boolean command() { if (move()) return true; if (penup()) return true; if (pendown()) return true; ...
My helper methods • I wrote a number of helper methods for the Parserand for the ParserTest classes • One very useful method is bt, in the ParserTest class • This method lets me build parse trees for use in assertEquals tests • Another is assertStackTop, which is just • private void assertStackTop(BinaryTree bt) { assertEquals(bt, parser.stack.peek());} • Example: • BinaryTree condition = bt("=", "2", "2");assertStackTop(bt("if", condition, "list"));