%{ /* -*- c -*- * Grammar for states. * Copyright (c) 1997-1998 Markku Rossi. * * Author: Markku Rossi */ /* * This file is part of GNU Enscript. * * Enscript is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Enscript is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Enscript. If not, see . */ /* * $Id: gram.y,v 1.1.1.1 2003/03/05 07:25:52 mtr Exp $ */ #include "defs.h" %} %union { List *lst; Node *node; Cons *cons; Stmt *stmt; Expr *expr; } %token tSYMBOL tREGEXP tSTRING tINTEGER tREAL %token tSUB tSTATE tSTART tSTARTRULES tNAMERULES tBEGIN tEND tRETURN tIF tELSE %token tLOCAL tWHILE tFOR tEXTENDS %right '=' tADDASSIGN tSUBASSIGN tMULASSIGN tDIVASSIGN %right '?' ':' %left tOR %left tAND %left tEQ tNE %left '<' '>' tGE tLE %left '+' '-' %left '*' tDIV %right '!' tPLUSPLUS tMINUSMINUS %left '[' ']' %type regexp_sym_list symbol_list rest_symbol_list staterules %type stmt_list expr_list rest_expr_list locals locals_rest %type stmt %type expr cond_expr %type staterule local_def %% file : /* empty */ | file toplevel ; toplevel : tSTART '{' stmt_list '}' { start_stmts = $3; } | tSTARTRULES '{' regexp_sym_list '}' { startrules = $3; } | tNAMERULES '{' regexp_sym_list '}' { namerules = $3; } | tSTATE tSYMBOL '{' staterules '}' { define_state ($2, NULL, $4); } | tSTATE tSYMBOL tEXTENDS tSYMBOL '{' staterules '}' { define_state ($2, $4, $6); } | stmt { list_append (global_stmts, $1); } ; regexp_sym_list : /* empty */ { $$ = list (); } | regexp_sym_list tREGEXP tSYMBOL ';' { list_append ($1, cons ($2, $3)); } ; staterules : /* empty */ { $$ = list (); } | staterules staterule { list_append ($1, $2); } staterule : tBEGIN '{' stmt_list '}' { $$ = cons (RULE_BEGIN, $3); } | tEND '{' stmt_list '}' { $$ = cons (RULE_END, $3); } | tREGEXP '{' stmt_list '}' { $$ = cons ($1, $3); } | tSYMBOL '{' stmt_list '}' { $$ = cons ($1, $3); } ; symbol_list : /* empty */ { $$ = list (); } | rest_symbol_list { $$ = $1; } ; rest_symbol_list : tSYMBOL { $$ = list (); list_append ($$, $1); } | rest_symbol_list ',' tSYMBOL { list_append ($1, $3); } ; locals : /* empty */ { $$ = list (); } | tLOCAL locals_rest ';' { $$ = $2; } ; locals_rest : local_def { $$ = list (); list_append ($$, $1); } | locals_rest ',' local_def { list_append ($1, $3); } ; local_def : tSYMBOL { $$ = cons ($1, NULL); } | tSYMBOL '=' expr { $$ = cons ($1, $3); } ; stmt_list : /* empty */ { $$ = list (); } | stmt_list stmt { list_append ($1, $2); } ; stmt : tRETURN ';' { $$ = mk_stmt (sRETURN, NULL, NULL, NULL, NULL); } | tRETURN expr ';' { $$ = mk_stmt (sRETURN, $2, NULL, NULL, NULL); } | tSUB tSYMBOL '(' symbol_list ')' '{' locals stmt_list '}' { $$ = mk_stmt (sDEFSUB, $2, cons (cons ($4, $7), $8), NULL, NULL); } | '{' stmt_list '}' { $$ = mk_stmt (sBLOCK, $2, NULL, NULL, NULL); } | tIF '(' expr ')' stmt { $$ = mk_stmt (sIF, $3, $5, NULL, NULL); } | tIF '(' expr ')' stmt tELSE stmt { $$ = mk_stmt (sIF, $3, $5, $7, NULL); } | tWHILE '(' expr ')' stmt { $$ = mk_stmt (sWHILE, $3, $5, NULL, NULL); } | tFOR '(' cond_expr ';' expr ';' cond_expr ')' stmt { $$ = mk_stmt (sFOR, $3, $5, $7, $9); } | expr ';' { $$ = mk_stmt (sEXPR, $1, NULL, NULL, NULL); } ; expr : tSTRING { $$ = mk_expr (eSTRING, $1, NULL, NULL); } | tREGEXP { $$ = mk_expr (eREGEXP, $1, NULL, NULL); } | tINTEGER { $$ = mk_expr (eINTEGER, $1, NULL, NULL); } | tREAL { $$ = mk_expr (eREAL, $1, NULL, NULL); } | tSYMBOL { $$ = mk_expr (eSYMBOL, $1, NULL, NULL); } | '!' expr { $$ = mk_expr (eNOT, $2, NULL, NULL); } | expr tAND expr { $$ = mk_expr (eAND, $1, $3, NULL); } | expr tOR expr { $$ = mk_expr (eOR, $1, $3, NULL); } | tSYMBOL '(' expr_list ')' { $$ = mk_expr (eFCALL, $1, $3, NULL); } | tSYMBOL '=' expr { $$ = mk_expr (eASSIGN, $1, $3, NULL); } | tSYMBOL tADDASSIGN expr { $$ = mk_expr (eADDASSIGN, $1, $3, NULL); } | tSYMBOL tSUBASSIGN expr { $$ = mk_expr (eSUBASSIGN, $1, $3, NULL); } | tSYMBOL tMULASSIGN expr { $$ = mk_expr (eMULASSIGN, $1, $3, NULL); } | tSYMBOL tDIVASSIGN expr { $$ = mk_expr (eDIVASSIGN, $1, $3, NULL); } | tSYMBOL tPLUSPLUS { $$ = mk_expr (ePOSTFIXADD, $1, NULL, NULL); } | tSYMBOL tMINUSMINUS { $$ = mk_expr (ePOSTFIXSUB, $1, NULL, NULL); } | tPLUSPLUS tSYMBOL { $$ = mk_expr (ePREFIXADD, $2, NULL, NULL); } | tMINUSMINUS tSYMBOL { $$ = mk_expr (ePREFIXSUB, $2, NULL, NULL); } | expr '[' expr ']' '=' expr { $$ = mk_expr (eARRAYASSIGN, $1, $3, $6); } | '(' expr ')' { $$ = $2; } | expr '[' expr ']' { $$ = mk_expr (eARRAYREF, $1, $3, NULL); } | expr '?' expr ':' expr { $$ = mk_expr (eQUESTCOLON, $1, $3, $5); } | expr '*' expr { $$ = mk_expr (eMULT, $1, $3, NULL); } | expr tDIV expr { $$ = mk_expr (eDIV, $1, $3, NULL); } | expr '+' expr { $$ = mk_expr (ePLUS, $1, $3, NULL); } | expr '-' expr { $$ = mk_expr (eMINUS, $1, $3, NULL); } | expr '<' expr { $$ = mk_expr (eLT, $1, $3, NULL); } | expr '>' expr { $$ = mk_expr (eGT, $1, $3, NULL); } | expr tEQ expr { $$ = mk_expr (eEQ, $1, $3, NULL); } | expr tNE expr { $$ = mk_expr (eNE, $1, $3, NULL); } | expr tGE expr { $$ = mk_expr (eGE, $1, $3, NULL); } | expr tLE expr { $$ = mk_expr (eLE, $1, $3, NULL); } ; cond_expr : /* empty */ { $$ = NULL; } | expr { $$ = $1; } ; expr_list : /* empty */ { $$ = list (); } | rest_expr_list { $$ = $1; } ; rest_expr_list: expr { $$ = list (); list_append ($$, $1); } | rest_expr_list ',' expr { list_append ($1, $3); } ; %% void yyerror (msg) char *msg; { fprintf (stderr, "%s:%d: %s\n", yyin_name, linenum, msg); }