/* File: SimpCompRecDescent.jpp Author: zerksis d. umrigar (zdu@acm.org) Copyright (C) 1997 Zerksis D. Umrigar Last Update Time-stamp: "97/06/27 20:42:09 umrigar" This code is distributed under the terms of the GNU General Public License. See the file COPYING with this distribution, or http://www.fsf.org/copyleft/gpl.html THERE IS ABSOLUTELY NO WARRANTY FOR THIS PROGRAM. */ package zdu.parsdemo; /* Straight-forward recursive-descent parser whose derivation from a translation scheme is sketched below: Parser for following translation scheme (terminals enclosed within single quotes or all upper-cased; semantic actions within braces; If a symbol S has a synthesized attribute s, then the symbol is shown as S(s). program : stmts ; stmts : assgnStmt | assgnStmt ';' stmts ; assgnStmt : ID ':=' expr ; expr : expr '+' term | expr '-' term | term ; term : term '*' factor | term '/' factor | term 'div' factor | term 'mod' factor | factor ; factor : '(' expr ')' | ID | NUM ; */ /* After removing left-recursion, to allow recursive-descent parsing: program : stmts ; stmts : assgnStmt stmtsRest ; stmtsRest : ';' stmts | EMPTY ; assgnStmt : ID ':=' expr ; expr : term exprRest ; exprRest : '+' term exprRest | '-' term exprRest | EMPTY ; term : factor termRest ; termRest : '*' factor termRest | '/' factor termRest | 'div' factor termRest | 'mod' factor termRest | EMPTY ; factor : '(' expr ')' | ID | NUM ; */ #define CALL(nonTerm) \ do { \ call((NonTerm) prgSyms.get(#nonTerm), ruleN, __LINE__); \ nonTerm(); \ } while (false) #define MATCH(tok) \ do { \ match((Terminal) prgSyms.get(#tok), ruleN, __LINE__); \ } while (false) #define RET() \ do { \ ret(ruleN, __LINE__); return; \ } while (false) #define ACCEPT() \ do { \ accept(ruleN, __LINE__); return; \ } while (false) #define RULE(n) int ruleN= n import zdu.parsdemo.NonTerm; import zdu.parsdemo.ParseException; import zdu.parsdemo.ParseResetException; import zdu.parsdemo.RecParser; import zdu.parsdemo.Scanner; import zdu.parsdemo.SimpCompLL1Gram; import zdu.parsdemo.Terminal; import java.util.Hashtable; class SimpCompRecDescent extends RecParser { SimpCompRecDescent(SimpCompLL1Gram grammar, Scanner scanner, ParseDisplay parseDisplay) { super(grammar, scanner, parseDisplay); prgSyms.put("assgnStmt", grammar.assgnStmt); prgSyms.put("expr", grammar.expr); prgSyms.put("exprRest", grammar.exprRest); prgSyms.put("factor", grammar.factor); prgSyms.put("program", grammar.program); prgSyms.put("stmts", grammar.stmts); prgSyms.put("stmtsRest", grammar.stmtsRest); prgSyms.put("term", grammar.term); prgSyms.put("termRest", grammar.termRest); prgSyms.put("'+'", grammar.ADD); prgSyms.put("ASSGN", grammar.ASSGN); prgSyms.put("DIV", grammar.DIV); prgSyms.put("'/'", grammar.DIVIDE); prgSyms.put("ID", grammar.ID); prgSyms.put("'('", grammar.LPAREN); prgSyms.put("MOD", grammar.MOD); prgSyms.put("'*'", grammar.MULT); prgSyms.put("NUM", grammar.NUM); prgSyms.put("')'", grammar.RPAREN); prgSyms.put("';'", grammar.SEMI); prgSyms.put("'-'", grammar.SUB); } SimpCompRecDescent(SimpCompLL1Gram grammar, Scanner scanner) { this(grammar, scanner, null); } protected final void parse() throws ParseException, ParseResetException { RULE(0); CALL(program); ACCEPT(); } private void program() throws ParseException, ParseResetException { RULE(1); CALL(stmts); } private void stmts() throws ParseException, ParseResetException { RULE(2); CALL(assgnStmt); CALL(stmtsRest); RET(); /* stmts() */ } private void stmtsRest() throws ParseException, ParseResetException { if (tok.getTokNum() == ';') { RULE(3); MATCH(';'); CALL(stmts); RET(); /* stmtsRest() */ } else { RULE(4); RET(); /* stmtsRest() */ } } private void assgnStmt() throws ParseException, ParseResetException { RULE(5); MATCH(ID); MATCH(ASSGN); CALL(expr); RET(); /* assgnStmt() */ } private void expr() throws ParseException, ParseResetException { RULE(6); CALL(term); CALL(exprRest); RET(); /* expr() */ } private void exprRest() throws ParseException, ParseResetException { if (tok.getTokNum() == '+') { RULE(7); MATCH('+'); CALL(term); CALL(exprRest); RET(); /* exprRest() */ } else if (tok.getTokNum() == '-') { RULE(8); MATCH('-'); CALL(term); CALL(exprRest); RET(); /* exprRest() */ } else { RULE(9); RET(); /* exprRest() */ } } private void term() throws ParseException, ParseResetException { RULE(10); CALL(factor); CALL(termRest); RET(); /* term() */ } private void termRest() throws ParseException, ParseResetException { if (tok.getTokNum() == '*') { RULE(11); MATCH('*'); CALL(factor); CALL(termRest); RET(); /* termRest() */ } else if (tok.getTokNum() == '/') { RULE(12); MATCH('/'); CALL(factor); CALL(termRest); RET(); /* termRest() */ } else if (tok.getTokNum() == SimpCompScanner.DIV_TOK) { RULE(13); MATCH(DIV); CALL(factor); CALL(termRest); RET(); /* termRest() */ } else if (tok.getTokNum() == SimpCompScanner.MOD_TOK) { RULE(14); MATCH(MOD); CALL(factor); CALL(termRest); RET(); /* termRest() */ } else { RULE(15); RET(); /* termRest() */ } } private void factor() throws ParseException, ParseResetException { if (tok.getTokNum() == '(') { RULE(16); MATCH('('); CALL(expr); MATCH(')'); RET(); /* factor() */ } else if (tok.getTokNum() == SimpCompScanner.ID_TOK) { RULE(17); MATCH(ID); RET(); /* factor() */ } else { RULE(18); String v= new String(scanner.lexemeText()); MATCH(NUM); RET(); /* factor() */ } } private Hashtable prgSyms= new Hashtable(); }