/************************************************************************ This program implements and tests a recursive descent parser for a language defined by a grammar given below. The parse tree constructor takes as its argument the name of a text file. It attempts to parse the text as a program in the language generated by the grammar. If the parse is successful, an appropriate parse tree is constructed. Otherwise a dummy parse tree is built and an appropriate error message is printed. The function "traverse" simply prints the tree if it is not a dummy. Otherwise it prints an error message. The function "yield" prints the sequence of the tokens in the leaves of a parse tree (from left to right). This should be the list of tokens in the string that was parsed. The "main" function simply tests the functions by calling it with a number of different text files. Each file is expected to be in the current directory. ************************************************************************/ // The grammar for the language is given below. Here nonterminals are // capitalized. The grammar has been expanded so that in each rule, // only tokens appear on the RHS of the arrow. // The start symbol is "Conditional". // Conditional -> ShortIf RestIf // ShortIf -> if Test then Block // RestIf -> else Block endif // RestIf -> endif // Test -> < Var Op Var> // Var -> x // Var -> y // Var -> z // Op -> = // Op -> /= // Block -> begin RestBlock // RestBlock -> end // RestBlock -> Statement Statements // Statements -> end // Statements -> Statement Statements // Statement -> Var := Var ////////////////////////////////// The "main" function //////////////////////////////////////////////////// #include "parse_tree.h" #include int main(void) { parser *p=new parser(); parse_tree *t=p->parse("data1.txt"); t->traverse(); cout << endl; t->display_yield(); cout << endl; delete t; t=p->parse("data2.txt"); t->traverse(); cout << endl; t->display_yield(); cout << endl; delete t; t=p->parse("data3.txt"); t->traverse(); cout << endl; t->display_yield(); cout << endl; delete t; t=p->parse("data4.txt"); t->traverse(); cout << endl; t->display_yield(); cout << endl; delete t; t=p->parse("data5.txt"); t->traverse(); cout << endl; t->display_yield(); cout << endl; delete t; t=p->parse("data6.txt"); t->traverse(); cout << endl; t->display_yield(); cout << endl; delete t; t=p->parse("data7.txt"); t->traverse(); cout << endl; t->display_yield(); cout << endl; delete t; t=p->parse("data8.txt"); t->traverse(); cout << endl; t->display_yield(); cout << endl; delete t; t=p->parse("data9.txt"); t->traverse(); cout << endl; t->display_yield(); cout << endl; delete t; t=p->parse("data10.txt"); t->traverse(); cout << endl; t->display_yield(); cout << endl; delete t; t=p->parse("data11.txt"); t->traverse(); cout << endl; t->display_yield(); cout << endl; delete t; t=p->parse("data12.txt"); t->traverse(); cout << endl; t->display_yield(); cout << endl; delete t; t=p->parse("data13.txt"); t->traverse(); cout << endl; t->display_yield(); cout << endl; delete t; t=p->parse("data14.txt"); t->traverse(); cout << endl; t->display_yield(); cout << endl; delete t; t=p->parse("data15.txt"); t->traverse(); cout << endl; t->display_yield(); cout << endl; delete t; t=p->parse("data16.txt"); t->traverse(); cout << endl; t->display_yield(); cout << endl; delete t; t=p->parse("data17.txt"); t->traverse(); cout << endl; t->display_yield(); cout << endl; delete t; t=p->parse("data18.txt"); t->traverse(); cout << endl; t->display_yield(); cout << endl; delete t; return 0; }