В языке
hocТребуется значительное число изменений для преобразования грамматики при переходе от
hoc5hoc6%union$cat hoc.y...%{#include "hoc.h"#define code2(c1,c2) code(c1); code(c2)#define code3(c1,c2,c3) code(c1); code(c2); code(c3)%}%union { Symbol *sym; /* symbol table pointer */ Inst *inst; /* machine instruction */ int narg; /* number of arguments */}%token <sym> NUMBER STRING PRINT VAR BLTIN UNDEF WHILE IF ELSE%token <sym> FUNCTION PROCEDURE RETURN FUNC PROC READ%token <narg> ARG%type <inst> expr stmt asgn prlist stmtlist%type <inst> cond while if begin end%type <sym> procname%type <narg> arglist%right '='%left OR%left AND%left GT GE LT LE EQ NE%left '+'%left '*' '/'%left UNARYMINUS NOT%right '^'%%list: /* nothing */ | list '\n' | list defn '\n' | list asgn '\n' { code2(pop, STOP); return 1; } | list stmt '\n' { code(STOP); return 1; } | list expr '\n' { code2(print, STOP); return 1; } | list error '\n' { yyerrok; } ;asgn: VAR '=' expr { code3(varpush,(Inst)$1,assign); $$=$3; } | ARG '=' expr { defnonly("$"); code2(argassign,(Inst)$1); $$=$3;} ;stmt: expr { code(pop); } | RETURN { defnonly("return"); code(procret); } | RETURN expr { defnonly("return"); $$=$2; code(funcret); } | PROCEDURE begin '(' arglist ')' { $$ = $2; code3(call, (Inst)$1, (Inst)$4); } | PRINT prlist { $$ = $2; } | while cond stmt end { ($1)[1] = (Inst)$3; /* body of loop */ ($1)[2] = (Inst)$4; } /* end, if cond fails */ | if cond stmt end { /* else-less if */ ($1)[1] = (Inst)$3; /* thenpart */ ($1)[3] = (Inst)$4; } /* end, if cond fails */ | if cond stmt end ELSE stmt end { /* if with else */ ($1)[1] = (Inst)$3; /* thenpart */ ($1)[2] = (Inst)$6; /* elsepart */ ($1)[3] = (Inst)$7; } /* end, if cond fails */ | '{' stmtlist '}' { $$ = $2; } ;cond: '(' expr ')' { code(STOP); $$ = $2; } ;while: WHILE { $$ = code3(whilecode,STOP,STOP); } ;if: IF { $$ = code(ifcode); code3(STOP, STOP, STOP); } ;begin: /* nothing */ { $$ = progp; } ;end: /* nothing */ { code(STOP); $$ = progp; } ;stmtlist: /* nothing */ { $$ = progp; } | stmtlist '\n' | stmtlist stmt ;expr: NUMBER { $$ = code2(constpush, (Inst)$1); } | VAR { $$ = code3(varpush, (Inst)$1, eval); } | ARG { defnonly("$"); $$ = code2(arg, (Inst)$1); } | asgn | FUNCTION begin '(' arglist ')' { $$ = $2; code3(call,(Inst)$1,(Inst)$4); } | READ '(' VAR ')' { $$ = code2(varread, (Inst)$3); } | BLTIN '(' expr ')' { $$=$3; code2(bltin, (Inst)$1->u.ptr); } | '(' expr ')' { $$ = $2; } | expr '+' expr { code(add); } | expr '-' expr { code(sub); } | expr '*' expr { code(mul); } | expr '/' expr { code(div); } | expr '^' expr { code (power); } | '-' expr %prec UNARYMINUS { $$=$2; code(negate); } | expr GT expr { code(gt); } | expr GE expr { code(ge); } | expr LT expr { code(lt); } | expr LE expr { code(le); }