/* * Copyrigth (C) 2002 Marcello Barnaba * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Christopher G. Demetriou. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Simple pascal RD Parser. * Developed on linux/i386. */ #include "rvp.h" #include "memory.h" #include "parse.h" #include "gettokname.h" #include "y.tab.h" #define boolean_expression expression int yylval; char *yylbuf; int tok = 0; int lookahead = 0; extern int yylex(); extern int line_num, pos_num; int main(void) { int ret; (void) printf("rvp v."RVP_VERSION" (C) 2002 Marcello Barnaba \n"); (void) printf("parsing %ssuccessfull\n", (ret = start()) ? "" : "un"); return ret == true ? EXIT_SUCCESS : EXIT_FAILURE; } _inline void error(char *s) { fprintf(stderr, "*** error: %s\n", s); } _inline int gettok() { if(lookahead) { tok = lookahead; lookahead = 0; } else tok = yylex(); return tok; } _inline void expected(char * expected) { fprintf(stderr, "[line %d:%d] unexpected token %s, expecting %s\n", line_num, pos_num, get_tok_name(tok), expected); } _inline void setla() { lookahead = tok; } /* grammar follows, one rule == one function. * * -------8<-------- REAL PARSING FUNCTIONS START HERE -------->8------- * * start: program_declarations . (* main program structure *) */ RD_func_t start() { if(program_declarations()) { if(gettok() == '.') return true; else expected("."); } error("wrong declarations"); return false; } /* program_declarations: * optional_head (* optional PROGRAM line *) | * declarations (* optional VAR`s *) | * compound_statement (* BEGIN .. END *) */ RD_func_t program_declarations() { if(optional_head() && declarations() && compound_statement()) return true; error("wrong body"); return false; } /* optional_head: lambda | PROGRAM identifier ; */ RD_func_t optional_head() { if(gettok() == PROGRAM) { if(gettok() == ID) { if(gettok() == ';') return true; else expected(";"); } expected("ID"); return false; } setla(); return true; } /* declarations: lambda | VAR identifier : predef_type ; declarations */ RD_func_t declarations() { if(gettok() == VAR) { if(gettok() == ID) { if(gettok() == ':') { if(predef_type()) { if(gettok() == ';') return declarations(); else expected(";"); } error("wrong type"); return false; } else expected(":"); } else expected("ID"); } setla(); return true; } /* predef_type: INTEGER | REAL | BOOLEAN | CHAR */ RD_func_t predef_type() { if(gettok() == INTEGER || tok == REAL || tok == BOOLEAN || tok == CHAR) return true; expected("PREDEF_TYPE"); return false; } /* statement: structured_statement (* seq, choice and iter *) | * declaring_statement (* declaration *) | * simple_statement (* assignment or call *) | * lambda */ RD_func_t statement() { gettok(); /* get the subsequent followers */ setla(); if(tok == BEGIN_ || tok == IF || tok == WHILE) return structured_statement(); else if (tok == VAR) return declaring_statement(); else if (tok == STRING || tok == ID) return simple_statement(); return true; } /* structured_statement: * compound_statement (* BEGIN .. END block *) | * conditional_statement (* IF block *) | * iterative_statement (* WHILE block *) */ RD_func_t structured_statement() { gettok(); /* get the followers */ setla(); if(tok == BEGIN_) return compound_statement(); else if (tok == IF) return conditional_statement(); else if (tok == WHILE) return iterative_statement(); expected("BEGIN or IF or WHILE"); return false; } /* compound_statement: BEGIN statement_list optional_semi END */ RD_func_t compound_statement() { if(gettok() == BEGIN_) { if(statement_list()) { if(optional_semi()) { if(gettok() == END) return true; else expected("END"); } else error("wrong semi"); } else error("wrong st.list"); return false; } expected("BEGIN"); return false; } /* conditional_statement: IF boolean_expression THEN statement optional_else */ RD_func_t conditional_statement() { if(gettok() == IF) { if(boolean_expression()) { if(gettok() == THEN) { if(statement()) return optional_else(); } expected("THEN"); } error("wrong expression"); return false; } expected("IF"); return false; } /* optional_else: lambda | * ELSE statement */ RD_func_t optional_else() { if(gettok() == ELSE) return statement(); setla(); return true; } /* iterative_statement: WHILE boolean_expression DO statement_list optional_semi */ RD_func_t iterative_statement() { if(gettok() == WHILE) { if(boolean_expression()) { if(gettok() == DO) { if(statement_list()) return optional_semi(); } else expected("DO"); } error("wrong w. expression"); return false; } expected("WHILE"); return false; } /* declaring_statement: VAR identifier : predef_type */ RD_func_t declaring_statement() { if(gettok() == VAR) { if(identifier()) { if(gettok() == ':') return predef_type(); else expected(":"); } error("wrong identifier"); return false; } expected("VAR"); return false; } /* simple_statement: identifier ( id_list ) | * identifier ASSIGN expression | * identifier */ RD_func_t simple_statement() { if(identifier()) { if(gettok() == '(') { if(id_list()) { if(gettok() == ')') return true; else expected(")"); } error("wrong id_list"); return false; } else if (tok == ASSIGN) { if (expression()) return true; } else { setla(); return true; } } error("Wrong simple stmt"); return false; } /* id_list: identifier | identifier , id_list */ RD_func_t id_list() { if(identifier()) { if(gettok() == ',') return id_list(); else { setla(); return true; } } error("wrong id"); return false; } /* statement_list: statement | statement ; statement_list */ RD_func_t statement_list() { if(statement()) { if(gettok() == ';') return statement_list(); else { setla(); return true; } } error("wrong stmt"); return false; } /* expression: simple_expression comparation_op simple_expression | * simple_expression */ RD_func_t expression() { if(simple_expression()) { if(comparation_op()) return simple_expression(); else return true; } return false; } /* simple_expression: term | * term plus_minus expression | * term OR expression | */ RD_func_t simple_expression() { if(term()) { if(plus_minus()) return simple_expression(); else if(gettok() == OR) return simple_expression(); else { setla(); return true; } } error("wrong term"); return false; } /* term: factor | factor mul_div term| factor AND term */ RD_func_t term() { if(factor()) { if(mul_div()) return term(); else if(gettok() == AND) return term(); else { setla(); return true; } } error("wrong factor"); return false; } /* factor: identifier | unsigned_number | BOOL_CONST | NOT factor */ RD_func_t factor() { if (identifier()) return true; if (unsigned_number()) return true; if (gettok() == BOOL_CONST) return true; else if(tok == NOT) return factor(); error("wrong fctr"); return false; } /* comparation_op: = | NE | < | > | LE | GE */ RD_func_t comparation_op() { if(gettok() == '=' || tok == NE || tok == '<' || tok == '>' || tok == LE || tok == GE) return true; setla(); return false; } /* mul_div: * | / | DIV | MOD */ RD_func_t mul_div() { if(gettok() == '*' || tok == '/' || tok == DIV || tok == MOD) return true; setla(); return false; } /* plus_minus: + | - */ RD_func_t plus_minus() { if(gettok() == '+' || tok == '-') return true; setla(); return false; } /* identifier: ID | STRING */ RD_func_t identifier() { if(gettok() == ID || tok == STRING) return true; setla(); return false; } /* optional_semi: lambda | ; */ RD_func_t optional_semi() { if(gettok() == ';') return true; setla(); return true; } /* unsigned_number = INT_CONST | REAL_CONST */ RD_func_t unsigned_number() { if(gettok() == INT_CONST || tok == REAL_CONST) return true; setla(); return false; } /* -------8<------------ END OF PARSING FUNCTIONS ------------>8------- */ /* vi:set ts=8 sts=4 sw=4 tw=79: */