Javascript函数声明野牛语法减少/减少错误

Javascript function declaration bison grammar reduce/reduce error

本文关键字:错误 语法 函数 声明 Javascript      更新时间:2023-09-26

我正在实现一个javascript解释器,我在野牛减少/减少函数声明和函数表达式语法中的冲突时遇到了问题。 我对野牛不是很有经验,我可以用一些帮助来理解该怎么做。 我已经粘贴了野牛输入文件的子集,说明了这个问题:

%define api.pure full
%{
#define YY_DECL int yylex '
    (YYSTYPE * yylval_param, yyscan_t yyscanner, parseData *pd)
%}
%union {  // yylval
    uint32_t slot;
    int64_t i;
    double d;
}
%{
void yyerror( void *scanner, parseData *pd, char *s, ... );
%}
%lex-param      { void *scanner } { parseData *pd }
%parse-param    { void *scanner } { parseData *pd }
%token <i>      INT
%token <d>      NUMBER
%token <slot>   STRING 
%token <slot>   NAME
%token          EOS
%token          FCN
%token          LPAR
%token          RPAR
%token          SEMI
%token          COMMA
%token          LBRACE
%token          RBRACE
%type <slot>    expr exprlist
%type <slot>    stmt
%type <slot>    paramlist
%type <slot>    funcdecl funcexpr
%type <slot>    fname
%type <slot>    symbol
%type <slot>    pgmlist
%start script
%%
script:
        EOS
        {
            pd->beginning = 0;
            YYACCEPT;
        }
    |   pgmlist
        {
            pd->beginning = $1;
            YYACCEPT;
        }
    ;
pgmlist:
        %empty
        {
            $$ = newNode(pd, node_endlist, sizeof(Node));
        }
    |   funcdecl pgmlist
        {
            $$ = newNode(pd, node_list, sizeof(listNode));
            listNode *ln = (listNode *)(pd->table + $$);
            ln->elem = $1;
        }
    |   stmt pgmlist
        {
            $$ = newNode(pd, node_list, sizeof(listNode));
            listNode *ln = (listNode *)(pd->table + $$);
            ln->elem = $1;
        }
    ;
funcdecl:
        FCN symbol LPAR paramlist RPAR LBRACE pgmlist RBRACE
        {
            $$ = newNode(pd, node_fcndecl, sizeof(fcnDeclNode));
            fcnDeclNode *fn = (fcnDeclNode *)(pd->table + $$);
            memset (fn, 0, sizeof(fcnDeclNode));
            fn->name = $2;
            fn->params = $4;
            fn->body = $7;
        }
   ;
funcexpr:
        FCN fname LPAR paramlist RPAR LBRACE pgmlist RBRACE
        {
            $$ = newNode(pd, node_fcndecl, sizeof(fcnDeclNode));
            fcnDeclNode *fn = (fcnDeclNode *)(pd->table + $$);
            memset (fn, 0, sizeof(fcnDeclNode));
            fn->name = $2;
            fn->params = $4;
            fn->body = $7;
        }
   ;
fname:
        %empty
        {
            $$ = 0;
        }
    |   NAME
        {
            fcnDeclNode *fn = (fcnDeclNode *)(pd->table + $1);
            fn->hdr->flag |= flag_decl | flag_lval;
            $$ = $1;
        }
    ;
stmt:  
        exprlist SEMI
        {
            $$ = $1;
        }
    ;
symbol:
        NAME
        {
            $$ = newNode(pd, node_var, sizeof(symNode));
            symNode *sn = (symNode *)(pd->table + $$);
            sn->name = $1;
        }
        ;
expr:   
        NUMBER
        {
            $$ = newNode(pd, node_num, sizeof(numNode));
            numNode *nn = (numNode *)(pd->table + $$);
            nn->value = $1;
        }
    |   STRING
        {
            $$ = $1;
        }
    |   funcexpr
        {
            $$ = $1;
        }
    ;
exprlist:     // non-empty
        expr 
        {
            newNode(pd, node_endlist, sizeof(Node));
        }
    |   expr COMMA exprlist
        {
            $$ = newNode(pd, node_list, sizeof(listNode));
            listNode *ln = (listNode *)(pd->table + $$);
            ln->elem = $1;
        }
    ;
paramlist:
        %empty
        {
            $$ = newNode(pd, node_endlist, sizeof(Node));
        }
    |   symbol 
        {
            symNode *sn = (symNode *)(pd->table + $1);
            sn->hdr->flag |= flag_decl;
            $$ = newNode(pd, node_list, sizeof(listNode));
            listNode *ln = (listNode *)(pd->table + $$);
            ln->elem = $1;
        }
    |   symbol COMMA paramlist
        {
            symNode *sn = (symNode *)(pd->table + $1);
            sn->hdr->flag |= flag_decl;
            $$ = newNode(pd, node_list, sizeof(listNode));
            listNode *ln = (listNode *)(pd->table + $$);
            ln->elem = $1;
        }
    ;
%%
void yyerror( void *scanner, parseData *pd, char *s, ... )
{
    fprintf(stderr, "yyerror: %s'n", s);
}

我通过意识到函数表达式只能用作赋值、声明值、参数、数组元素或对象值来解决此问题。 我放弃了立即调用的情况。它本身不需要归纳到一般表达式中。

我以前以同样的方式解决了对象文字生产。 这是我正在实现的javascript子集的完整语法:

%define api.pure full
%error-verbose
%{
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "jsdb.h"
#define YY_DECL int yylex '
    (YYSTYPE * yylval_param, yyscan_t yyscanner, parseData *pd)
%}
%union {  // yylval
    uint32_t slot;
    int64_t i;
    double d;
}
%{
#include "jsdb.lex.h"
static bool debug = true;
void yyerror( void *scanner, parseData *pd, char *s, ... );
%}
%lex-param      { void *scanner } { parseData *pd }
%parse-param    { void *scanner } { parseData *pd }
%token <i>      INT
%token <d>      NUMBER
%token <slot>   STRING 
%token <slot>   NAME
%token          EOS
%token          IF
%token          ELSE
%token          WHILE
%token          DO
%token          FOR
%token          FCN
%token          VAR
%token          RETURN
%token          CONTINUE
%token          BREAK
%token          AMPER
%token          LPAR
%token          RPAR
%token          SEMI
%token          COMMA
%token          LBRACE
%token          RBRACE
%token          LBRACK
%token          RBRACK
%token          COLON
%token          DOT
%right          RPAR ELSE
%precedence     PLUS_ASSIGN MINUS_ASSIGN ASSIGN
%left           LT LE EQ NEQ GT GE
%left           PLUS MINUS
%left           TIMES DIV
%precedence     UMINUS
%precedence     LPAR
%precedence     LBRACK
%precedence     DOT
%type <slot>    expr exprlist
%type <slot>    decl decllist
%type <slot>    arg arglist
%type <slot>    stmt stmtlist
%type <slot>    paramlist
%type <slot>    elem elemlist
%type <slot>    lval objlit
%type <slot>    arrayelem arraylist 
%type <slot>    funcdef funcexpr
%type <slot>    fname pgmlist
%type <slot>    symbol optexpr
%start script
%%
script:
        EOS
        {
            if (debug) printf("script -> EOS'n");
            pd->beginning = 0;
            YYACCEPT;
        }
    |   pgmlist
        {
            if (debug) printf("script -> pgmlist'n");
            pd->beginning = $1;
            YYACCEPT;
        }
    ;
pgmlist: 
        %empty
        {
            if (debug) printf("pgmlist -> _empty_'n");
            $$ = newNode(pd, node_endlist, sizeof(Node));
        }
    |   stmt pgmlist 
        {
            if (debug) printf("pgmlist -> stmt pgmlist'n");
            $$ = newNode(pd, node_list, sizeof(listNode));
            listNode *ln = (listNode *)(pd->table + $$);
            ln->elem = $1;
        }
    |   funcdef pgmlist 
        {
            if (debug) printf("pgmlist -> funcdef pgmlist'n");
            $$ = newNode(pd, node_list, sizeof(listNode));
            listNode *ln = (listNode *)(pd->table + $$);
            ln->elem = $1;
        }
    ;
funcdef:
        FCN symbol LPAR paramlist RPAR LBRACE stmtlist RBRACE
        {
            if (debug) printf("funcdef -> symbol fname LPAR paramlist RPAR LBRACE stmtlist RBRACE'n");
            $$ = newNode(pd, node_fcnexpr, sizeof(fcnDeclNode));
            fcnDeclNode *fn = (fcnDeclNode *)(pd->table + $$);
            memset (fn, 0, sizeof(fcnDeclNode));
            fn->hdr->flag |= flag_decl;
            fn->name = $2;
            fn->params = $4;
            fn->body = $7;
        }
   ;
funcexpr:
        FCN fname LPAR paramlist RPAR LBRACE stmtlist RBRACE
        {
            if (debug) printf("funcexpr -> FCN fname LPAR paramlist RPAR LBRACE stmtlist RBRACE'n");
            $$ = newNode(pd, node_fcnexpr, sizeof(fcnDeclNode));
            fcnDeclNode *fn = (fcnDeclNode *)(pd->table + $$);
            memset (fn, 0, sizeof(fcnDeclNode));
            fn->name = $2;
            fn->params = $4;
            fn->body = $7;
        }
   ;
fname:
        %empty
        {
            if (debug) printf("fname -> _empty_'n");
            $$ = 0;
        }
    |   NAME
        {
            if (debug) printf("fname -> NAME'n");
            $$ = $1;
        }
    ;
stmt:  
        IF LPAR expr RPAR stmt
        {
            if (debug) printf("stmt -> IF LPAR expr RPAR stmt'n");
            $$ = newNode(pd, node_ifthen, sizeof(ifThenNode));
            ifThenNode *ifthen = (ifThenNode *)(pd->table + $$);
            ifthen->condexpr = $3;
            ifthen->thenstmt = $5;
            ifthen->elsestmt = 0;
        }
    |   IF LPAR expr RPAR stmt ELSE stmt
        {
            if (debug) printf("stmt -> IF LPAR expr RPAR stmt ELSE stmt'n");
            $$ = newNode(pd, node_ifthen, sizeof(ifThenNode));
            ifThenNode *ifthen = (ifThenNode *)(pd->table + $$);
            ifthen->condexpr = $3;
            ifthen->thenstmt = $5;
            ifthen->elsestmt = $7;
        }
    |   RETURN optexpr SEMI
        {
            if (debug) printf("stmt -> RETURN optexpr SEMI'n");
            $$ = newNode(pd, node_return, sizeof(exprNode));
            exprNode *en = (exprNode *)(pd->table + $$);
            en->expr = $2;
        }
    |   BREAK SEMI
        {
            if (debug) printf("stmt -> BREAK SEMI'n");
            $$ = newNode(pd, node_return, sizeof(exprNode));
            exprNode *en = (exprNode *)(pd->table + $$);
            en->hdr->flag |= flag_break;
        }
    |   CONTINUE SEMI
        {
            if (debug) printf("stmt -> CONTINUE SEMI'n");
            $$ = newNode(pd, node_return, sizeof(exprNode));
            exprNode *en = (exprNode *)(pd->table + $$);
            en->hdr->flag |= flag_continue;
        }
    |   WHILE LPAR expr RPAR stmt
        {
            if (debug) printf("stmt -> WHILE LPAR expr RPAR stmt'n");
            $$ = newNode(pd, node_while, sizeof(whileNode));
            whileNode *wn = (whileNode *)(pd->table + $$);
            wn->cond = $3;
            wn->stmt = $5;
        }
    |   DO stmt WHILE LPAR expr RPAR SEMI
        {
            if (debug) printf("stmt -> DO stmt WHILE LPAR expr RPAR SEMI'n");
            $$ = newNode(pd, node_dowhile, sizeof(whileNode));
            whileNode *wn = (whileNode *)(pd->table + $$);
            wn->cond = $5;
            wn->stmt = $2;
        }
    |   FOR LPAR expr SEMI expr SEMI expr RPAR stmt
        {
            if (debug) printf("stmt -> FOR LPAR expr SEMI expr SEMI expr RPAR stmt'n");
            $$ = newNode(pd, node_for, sizeof(forNode));
            forNode *fn = (forNode *)(pd->table + $$);
            fn->init = $3;
            fn->cond = $5;
            fn->incr = $7;
            fn->stmt = $9;
        }
    |   LBRACE stmtlist RBRACE
        {
            if (debug) printf("stmt -> LBRACE stmtlist RBRACE'n");
            $$ = $2;
        }
    |   VAR decllist SEMI
        {
            if (debug) printf("stmt -> VAR decllist SEMI'n");
            $$ = $2;
        }
    |   exprlist SEMI
        {
            if (debug) printf("stmt -> exprlist SEMI'n");
            $$ = $1;
        }
    |   SEMI
        {
            if (debug) printf("stmt -> _empty_'n");
            $$ = 0;
        }
    ;
stmtlist: 
        %empty
        {
            if (debug) printf("stmtlist -> _empty_'n");
            $$ = newNode(pd, node_endlist, sizeof(Node));
        }
    |   stmt stmtlist 
        {
            if (debug) printf("stmtlist -> stmt stmtlist'n");
            $$ = newNode(pd, node_list, sizeof(listNode));
            listNode *ln = (listNode *)(pd->table + $$);
            ln->elem = $1;
        }
    ;
symbol:
        NAME
        {
            if (debug) {
                stringNode *sn = (stringNode *)(pd->table + $1);
                printf("symbol -> NAME[%.*s]'n", sn->hdr->aux, sn->string);
            }
            $$ = newNode(pd, node_var, sizeof(symNode));
            symNode *sn = (symNode *)(pd->table + $$);
            sn->name = $1;
        }
        ;
decl:
        symbol
        {
            if (debug) printf("decl -> symbol'n");
            symNode *sn = (symNode *)(pd->table + $1);
            sn->hdr->flag |= flag_decl;
            $$ = $1;
        }
    |   symbol ASSIGN expr
        {
            if (debug) printf("decl -> symbol ASSIGN expr'n");
            symNode *sn = (symNode *)(pd->table + $1);
            sn->hdr->flag |= flag_lval | flag_decl;
            $$ = newNode(pd, node_assign, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->hdr->aux = pm_assign;
            bn->right = $3;
            bn->left = $1;
        }
    |   symbol ASSIGN funcexpr
        {
            if (debug) printf("decl -> symbol ASSIGN funcexpr'n");
            symNode *sn = (symNode *)(pd->table + $1);
            sn->hdr->flag |= flag_lval | flag_decl;
            $$ = newNode(pd, node_assign, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->hdr->aux = pm_assign;
            bn->right = $3;
            bn->left = $1;
        }
    |   symbol ASSIGN objlit
        {
            if (debug) printf("decl -> symbol ASSIGN objlit'n");
            symNode *sn = (symNode *)(pd->table + $1);
            sn->hdr->flag |= flag_lval | flag_decl;
            $$ = newNode(pd, node_assign, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->hdr->aux = pm_assign;
            bn->right = $3;
            bn->left = $1;
        }
    ;
decllist:
        decl
        {
            if (debug) printf("decllist -> decl'n");
            newNode(pd, node_endlist, sizeof(Node));
            $$ = newNode(pd, node_list, sizeof(listNode));
            listNode *ln = (listNode *)(pd->table + $$);
            ln->elem = $1;
        }
    |
        decl COMMA decllist
        {
            if (debug) printf("decllist -> decl COMMA decllist'n");
            $$ = newNode(pd, node_list, sizeof(listNode));
            listNode *ln = (listNode *)(pd->table + $$);
            ln->elem = $1;
        }
    ;
expr:   
        expr LT expr
        {
            if (debug) printf("expr -> expr LT expr'n");
            $$ = newNode(pd, node_lt, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->right = $3;
            bn->left = $1;
        }
    |   expr LE expr
        {
            if (debug) printf("expr -> expr LE expr'n");
            $$ = newNode(pd, node_le, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->right = $3;
            bn->left = $1;
        }
    |   expr EQ expr
        {
            if (debug) printf("expr -> expr EQ expr'n");
            $$ = newNode(pd, node_eq, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->right = $3;
            bn->left = $1;
        }
    |   expr NEQ expr
        {
            if (debug) printf("expr -> expr NEQ expr'n");
            $$ = newNode(pd, node_ne, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->right = $3;
            bn->left = $1;
        }
    |   expr GE expr
        {
            if (debug) printf("expr -> expr GE expr'n");
            $$ = newNode(pd, node_ge, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->right = $3;
            bn->left = $1;
        }
    |   expr GT expr
        {
            if (debug) printf("expr -> expr GT expr'n");
            $$ = newNode(pd, node_gt, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->right = $3;
            bn->left = $1;
        }
    |   expr PLUS expr
        {
            if (debug) printf("expr -> expr PLUS expr'n");
            $$ = newNode(pd, node_plus, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->right = $3;
            bn->left = $1;
        }
    |   expr MINUS expr
        {
            if (debug) printf("expr -> expr MINUS expr'n");
            $$ = newNode(pd, node_minus, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->right = $3;
            bn->left = $1;
        }
    |   expr TIMES expr
        {
            if (debug) printf("expr -> expr TIMES expr'n");
            $$ = newNode(pd, node_times, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->right = $3;
            bn->left = $1;
        }
    |   expr DIV expr
        {
            if (debug) printf("expr -> expr DIV expr'n");
            $$ = newNode(pd, node_div, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->right = $3;
            bn->left = $1;
        }
    |   LPAR exprlist RPAR
        {
            if (debug) printf("expr -> LPAR expr RPAR'n");
            $$ = $2;
        }
    |   MINUS expr %prec UMINUS
        {
            if (debug) printf("expr -> UMINUS expr'n");
            $$ = newNode(pd, node_uminus, sizeof(exprNode));
            exprNode *en = (exprNode *)(pd->table + $$);
            en->expr = $2;
        }
    |   NUMBER
        {
            if (debug) printf("expr -> NUMBER[%f]'n", $1);
            $$ = newNode(pd, node_num, sizeof(numNode));
            numNode *nn = (numNode *)(pd->table + $$);
            nn->value = $1;
        }
    |   INT
        {
            if (debug) printf("expr -> INT[%d]'n", $1);
            $$ = newNode(pd, node_int, sizeof(intNode));
            intNode *in = (intNode *)(pd->table + $$);
            in->value = $1;
        }
    |   STRING
        {
            if (debug) {
                stringNode *sn = (stringNode *)(pd->table + $1);
                printf("expr -> STRING[%.*s]'n", sn->hdr->aux, sn->string);
            }
            $$ = $1;
        }
    |   lval ASSIGN expr
        {
            if (debug) printf("expr -> lval ASSIGN expr'n");
            symNode *sn = (symNode *)(pd->table + $1);
            sn->hdr->flag |= flag_lval;
            $$ = newNode(pd, node_assign, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->hdr->aux = pm_assign;
            bn->right = $3;
            bn->left = $1;
        }
    |   lval ASSIGN funcexpr
        {
            if (debug) printf("expr -> lval ASSIGN funcexpr'n");
            symNode *sn = (symNode *)(pd->table + $1);
            sn->hdr->flag |= flag_lval;
            $$ = newNode(pd, node_assign, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->hdr->aux = pm_assign;
            bn->right = $3;
            bn->left = $1;
        }
    |   lval ASSIGN objlit
        {
            if (debug) printf("expr -> lval ASSIGN objlit'n");
            symNode *sn = (symNode *)(pd->table + $1);
            sn->hdr->flag |= flag_lval;
            $$ = newNode(pd, node_assign, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->hdr->aux = pm_assign;
            bn->right = $3;
            bn->left = $1;
        }
    |   lval PLUS_ASSIGN expr
        {
            if (debug) printf("expr -> lval PLUS_ASSIGN expr'n");
            symNode *sn = (symNode *)(pd->table + $1);
            sn->hdr->flag |= flag_lval;
            $$ = newNode(pd, node_assign, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->hdr->aux = pm_add;
            bn->right = $3;
            bn->left = $1;
        }
    |   lval MINUS_ASSIGN expr
        {
            if (debug) printf("expr -> lval MINUS_ASSIGN expr'n");
            symNode *sn = (symNode *)(pd->table + $1);
            sn->hdr->flag |= flag_lval;
            $$ = newNode(pd, node_assign, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->hdr->aux = pm_sub;
            bn->right = $3;
            bn->left = $1;
        }
    |   expr LPAR arglist RPAR
        {
            if (debug) printf("expr -> expr LPAR arglist RPAR'n");
            $$ = newNode(pd, node_fcncall, sizeof(fcnCallNode));
            fcnCallNode *fc = (fcnCallNode *)(pd->table + $$);
            fc->name = $1;
            fc->args = $3;
        }
    |   LBRACK arraylist RBRACK
        {
            if (debug) printf("expr -> LBRACK arraylist RBRACK'n");
            $$ = newNode(pd, node_array, sizeof(arrayNode));
            arrayNode *an = (arrayNode *)(pd->table + $$);
            an->exprlist = $2;
        }
    |   lval
        {
            if (debug) printf("expr -> lval'n");
            $$ = $1;
        }
    ;
optexpr:
        %empty
        {
            if (debug) printf("optexpr -> _empty_'n");
            $$ = 0;
        }
    |   expr
        {
            if (debug) printf("optexpr -> expr'n");
            $$ = $1;
        }
    ;
arrayelem:
        expr
        {
            if (debug) printf("arrayelem -> expr'n");
            $$ = $1;
        }
    |   funcexpr
        {
            if (debug) printf("arrayelem -> funcexpr'n");
            $$ = $1;
        }
    |   objlit
        {
            if (debug) printf("arrayelem -> objlit'n");
            $$ = $1;
        }
    ;
arraylist:
        %empty
        {
            if (debug) printf("arraylist -> _empty_'n");
            newNode(pd, node_endlist, sizeof(Node));
        }
    |   arrayelem
        {
            if (debug) printf("arraylist -> arrayelem'n");
            $$ = newNode(pd, node_list, sizeof(listNode));
            listNode *ln = (listNode *)(pd->table + $$);
            ln->elem = $1;
        }
    |   arrayelem COMMA arraylist
        {
            if (debug) printf("arraylist -> arrayelem COMMA arraylist'n");
            $$ = newNode(pd, node_list, sizeof(listNode));
            listNode *ln = (listNode *)(pd->table + $$);
            ln->elem = $1;
        }
    ;
lval:
        symbol
        {
            $$ = $1;
        }
    |   expr DOT NAME
        {
            if (debug) {
                stringNode *sn = (stringNode *)(pd->table + $3);
                printf("lval -> expr DOT NAME[%.*s]'n", sn->hdr->aux, sn->string);
            }
            $$ = newNode(pd, node_lookup, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->right = $3;
            bn->left = $1;
        }
    |   expr LBRACK expr RBRACK
        {
            if (debug) printf("lval -> expr LBRACK expr RBRACK'n");
            $$ = newNode(pd, node_lookup, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->right = $3;
            bn->left = $1;
        }
    ;
exprlist:     // non-empty
        expr 
        {
            if (debug) printf("exprlist -> expr'n");
            newNode(pd, node_endlist, sizeof(Node));
            $$ = newNode(pd, node_list, sizeof(listNode));
            listNode *ln = (listNode *)(pd->table + $$);
            ln->elem = $1;
        }
    |   expr COMMA exprlist
        {
            if (debug) printf("exprlist -> expr COMMA exprlist'n");
            $$ = newNode(pd, node_list, sizeof(listNode));
            listNode *ln = (listNode *)(pd->table + $$);
            ln->elem = $1;
        }
    ;
objlit:
        LBRACE elemlist RBRACE 
        {
            if (debug) printf("objlit -> LBRACE elemlist RBRACE'n");
            $$ = newNode(pd, node_obj, sizeof(objNode));
            objNode *on = (objNode *)(pd->table + $$);
            on->elemlist = $2;
        }
    ;
elemlist:
        %empty
        {
            if (debug) printf("elemlist -> _empty_'n");
            $$ = newNode(pd, node_endlist, sizeof(Node));
        }
    |   elem
        {
            if (debug) printf("elemlist -> elem'n");
            $$ = newNode(pd, node_list, sizeof(listNode));
            listNode *ln = (listNode *)(pd->table + $$);
            ln->elem = $1;
        }
    |   elem COMMA elemlist
        {
            if (debug) printf("elemlist -> elem COMMA elemlist'n");
            $$ = newNode(pd, node_list, sizeof(listNode));
            listNode *ln = (listNode *)(pd->table + $$);
            ln->elem = $1;
        }
    ;
elem:
        NAME COLON expr
        {
            if (debug) {
                stringNode *sn = (stringNode *)(pd->table + $1);
                printf("elem -> NAME[%.*s] COLON expr'n", sn->hdr->aux, sn->string);
            }
            $$ = newNode(pd, node_elem, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->right = $3;
            bn->left = $1;
        }
    |   STRING COLON expr
        {
            if (debug) {
                stringNode *sn = (stringNode *)(pd->table + $1);
                printf("elem -> STRING[%.*s] COLON expr'n", sn->hdr->aux, sn->string);
            }
            $$ = newNode(pd, node_elem, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->right = $3;
            bn->left = $1;
        }
    |   NAME COLON funcexpr
        {
            if (debug) {
                stringNode *sn = (stringNode *)(pd->table + $1);
                printf("elem -> NAME[%.*s] COLON funcexpr'n", sn->hdr->aux, sn->string);
            }
            $$ = newNode(pd, node_elem, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->right = $3;
            bn->left = $1;
        }
    |   NAME COLON objlit
        {
            if (debug) {
                stringNode *sn = (stringNode *)(pd->table + $1);
                printf("elem -> NAME[%.*s] COLON objlit'n", sn->hdr->aux, sn->string);
            }
            $$ = newNode(pd, node_elem, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->right = $3;
            bn->left = $1;
        }
    |   STRING COLON funcexpr
        {
            if (debug) {
                stringNode *sn = (stringNode *)(pd->table + $1);
                printf("elem -> STRING[%.*s] COLON funcexpr'n", sn->hdr->aux, sn->string);
            }
            $$ = newNode(pd, node_elem, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->right = $3;
            bn->left = $1;
        }
    |   STRING COLON objlit
        {
            if (debug) {
                stringNode *sn = (stringNode *)(pd->table + $1);
                printf("elem -> STRING[%.*s] COLON objlit'n", sn->hdr->aux, sn->string);
            }
            $$ = newNode(pd, node_elem, sizeof(binaryNode));
            binaryNode *bn = (binaryNode *)(pd->table + $$);
            bn->right = $3;
            bn->left = $1;
        }
    ;
paramlist:
        %empty
        {
            if (debug) printf("paramlist -> _empty_'n");
            $$ = newNode(pd, node_endlist, sizeof(Node));
        }
    |   symbol 
        {
            if (debug) printf("paramlist -> symbol'n");
            symNode *sn = (symNode *)(pd->table + $1);
            sn->hdr->flag |= flag_decl;
            $$ = newNode(pd, node_list, sizeof(listNode));
            listNode *ln = (listNode *)(pd->table + $$);
            ln->elem = $1;
        }
    |   symbol COMMA paramlist
        {
            if (debug) printf("paramlist -> symbol COMMA paramlist'n");
            symNode *sn = (symNode *)(pd->table + $1);
            sn->hdr->flag |= flag_decl;
            $$ = newNode(pd, node_list, sizeof(listNode));
            listNode *ln = (listNode *)(pd->table + $$);
            ln->elem = $1;
        }
    ;
arg:
       AMPER symbol
        {
            if (debug) printf("arg -> AMPER symbol'n");
            symNode *sn = (symNode *)(pd->table + $2);
            sn->hdr->type = node_ref;
            $$ = $2;
        }
    |   expr
        {
            if (debug) printf("arg -> expr'n");
            $$ = $1;
        }
    |   funcexpr
        {
            if (debug) printf("arg -> funcexpr'n");
            $$ = $1;
        }
    |   objlit
        {
            if (debug) printf("arg -> objlit'n");
            $$ = $1;
        }
    ;
arglist:
        %empty
        {
            if (debug) printf("arglist -> _empty_'n");
            $$ = newNode(pd, node_endlist, sizeof(Node));
        }
    |   arg
        {
            if (debug) printf("arglist -> arg'n");
            $$ = newNode(pd, node_list, sizeof(listNode));
            listNode *ln = (listNode *)(pd->table + $$);
            ln->elem = $1;
        }
    |   arg COMMA arglist
        {
            if (debug) printf("arglist -> arg COMMA arglist'n");
            $$ = newNode(pd, node_list, sizeof(listNode));
            listNode *ln = (listNode *)(pd->table + $$);
            ln->elem = $1;
        }
    ;
%%
void yyerror( void *scanner, parseData *pd, char *s, ... )
{
    fprintf(stderr, "yyerror: %s'n", s);
}
相关文章: