%{ /* This is a sample parser file for input to yacc. * It recognizes a very simple subset of C with * assignment statements and if-then and if-then-else. * In order to illustrate the S/R conflict in the latter * there are no semicolons at the end of statements. (Naturally * you will need to add semicolons in your language....) * * The main things to remember are * o The command sequences to compile the yacc and lex input * files is given on p.59 of the Lex and Yacc book, except * I use gcc instead of cc and the file names are different: * * yacc -dv parsamp2.y (this produces y.tab.c, y.tab.h, and y.output) * lex lexsamp2.l (this produces lex.yy.c) * gcc y.tab.c lex.yy.c -ly -ll (this produces a.out) * a.out < sampledata2.c * * Or you can just type lines to the a.out file. See p. 59-60 in * the Lex & Yacc book. You might want to make a Make file. * o Using this method of linking lex and yacc, the assignment of * numbers to tokens is done by yacc, not by you in your * lex input file. The -d flag will create a y.tab.h file * in which #DEFINE statements are produced for all tokens * declared with %token, %nonassoc, etc. (take a look). See * pp.58-59 and 203 in the L&Y book for a brief discussion * of these issues. The -v flag creates the log file y.output * which records the items in each state, and the R/R and S/R * conflicts (if any). Search for "conflict" in this file, and * note that the underscore "_" is same as dot for LR(0) items. o If you want to define a function or variable in the lex source file * and use it here (say, a line buffer to store the current line to be * printed out on an error), you need to give an extern declaration at the * top of the file, since these files are compiled separates and then * linked. * o The symbol table is not used yet, so it should * be left alone to accumulate identifiers. We'll make * use of it in the third phase of the compiler. * o In the L & Y book, it talks about the "value" * of grammar symbols; this is not relevant yet, and should * be ignored. * o The only actions associated with the rules are the * printf statements that trace the reductions. * o To do error reporting for syntax errors, insert a function * * yyerror(char *s) { ... etc. } * * at the bottom of your yacc file; this will be called whenever * a syntax error is found, e.g., when the ERROR token is found by * your lexer. Lexical errors must be handled by the lexer, or * set a global flag that indicates when yyerror is called that * the error was lexical. */ %} %token MAIN %token IF %token LPAREN %token RPAREN %token LBRACE %token RBRACE %token ELSE %token SEMICOLON %token ID %token NUM %token ASSIGN %token ERROR %% prog : MAIN LPAREN RPAREN compStmt { printf("1 Success!\n"); } ; compStmt : LBRACE stmtList RBRACE { printf("2, "); } ; stmtList : stmt { printf("3\n"); } | stmtList stmt { printf("4\n"); } ; stmt : ID ASSIGN expr { printf("5, "); } | IF expr stmt { printf("6, "); } | IF expr stmt ELSE stmt { printf("7, "); } ; expr : ID { printf("8, "); } | NUM { printf("9, "); } ; %%