簡體   English   中英

Yacc語法產生錯誤的終端

[英]Yacc grammar producing incorrect terminal

我一直在從事一個業余編譯器一段時間,在解析階段使用lex和yacc。 對於大多數事情來說,這一切都很好,但是當我添加if語句時,符號的生產規則現在在堆棧上給出了上一個(或下一個?)項目,而不是所需的符號值。

下面給出語法,並希望刪除不相關的規則:

%{
       ...
%}


    %define parse.error verbose


    %token ...

    %%


    Program:
            Function                                            { root->addChild($1);}      
            ;


    Function:
            Type Identifier '|' ArgumentList '|' StatementList END
                                                                { $$ = new FunctionDef($1, $2, $4, $6); }


    /******************************************/
    /* Statements and control flow ************/
    /******************************************/

    Statement:
            Expression Delimiter
            | VariableDeclaration Delimiter
            | ControlFlowStatement Delimiter
            | Delimiter
            ;

    ControlFlowStatement:
            IfStatement
            ;

    IfStatement:
            IF Expression StatementList END                       { $$ = new IfStatement($2, $3); }
            | IF Expression StatementList ELSE StatementList END  { $$ = new IfStatement($2, $3, $5);}
            ;

    VariableDeclaration:
            Type Identifier                                     { $$ = new VariableDeclaration($1, $2);}
            | Type Identifier EQUALS Expression                 { $$ = new VariableDeclaration($1, $2, $4);}
            ;

    StatementList:
            StatementList Statement                             { $1->addChild($2);             }
            | Statement                                         { $$ = new GenericList($1);     }
            ;


    Delimiter:
            ';'
            | NEWLINE
            ;
    Type:
           ...
Expression:
    ...

    PostfixExpression:
            Value '[' Expression ']'                            { std::cout << "TODO: indexing operators ([ ])" << std::endl;}
            | Value '.' SYMBOL                                  { std::cout << "TODO: member access" << std::endl;}
            | Value INCREMENT                                   { $$ = new UnaryExpression(UNARY_POSTINC, $1);  }
            | Value DECREMENT                                   { $$ = new UnaryExpression(UNARY_POSTDEC, $1);  }
            | Value '(' ')'                                     { $$ = new FunctionCall($1, NULL);    }
            | Value '(' ExpressionList ')'                      { $$ = new FunctionCall($1, $3);                }
            | Value
            ;


    Value:
            BININT                                              { $$ = new Integer(yytext, 2);                  }
            | HEXINT                                            { $$ = new Integer(yytext, 16);                 }
            | DECINT                                            { $$ = new Integer(yytext);                     }
            | FLOAT                                             { $$ = new Float(yytext);                       }
            | SYMBOL                                            { $$ = new Symbol(yytext);                      }
            | STRING                                            { $$ = new String(yytext);                      }
            | LambdaFunction
            | '(' Expression ')'                                { $$ = $2;                                      }
            | '[' ExpressionList ']'                            { $$ = $2;}
            ;

    LambdaFunction:
            ...


    %%

我無法弄清楚控制流代碼如何使Symbol:規則與lex定義中未歸類為符號的內容匹配:

symbol                      [a-zA-Z_]+(alpha|digit)*
...
{symbol}                    {return SYMBOL;}

任何對yacc和語法有一般了解的人的幫助將不勝感激。 如果需要,還可以顯示其解析的語法的示例文件。

謝謝!

您不能依靠flex動作之外的yytext值。

野牛語法通常在決定如何進行前先讀取先行標記,因此在野牛操作中, yytext已被先行標記的標記值代替。 (不過,您也不能指望這一點:有時不需要先行令牌。)

因此,您需要在flex動作返回之前制作yytext的副本,並通過將其放入yylval語義並集使該副本可用於野牛語法。

查看此野牛常見問題解答條目


順便說一句,您的flex文件中的以下代碼段不正確:

symbol                      [a-zA-Z_]+(alpha|digit)*

在該正則表達式中, alphadigit只是普通字符串,因此與[a-zA-Z_]+("alpha"|"digit")* ,這意味着它將與例如a_digitdigitdigit匹配,但不是a_123 (它應該與a_digitdigitdigit匹配,而+ a_digitdigitdigit沒有部分,所以我認為這不是您的意圖。)

總的來說,我認為使用Posix字符類比使用手寫字符類或定義的符號更好,因此我將其寫為

symbol    [[:alpha:]_]([[:alnum:]_]*[[:alnum:]])?

假設您的意圖是符號可以以下划線開頭但不能以下划線結尾,而不能以數字開頭但不能以數字開頭。 使用Posix字符類要求您使用正確的語言環境(幾乎可以肯定是C語言環境)執行flex,但是字符范圍也是如此 ,因此使用自記錄的Posix類不會丟失任何內容。

(當然,我不知道您對{alpha}{digit}定義是什么,但在我看來,它們在[[:alpha:]][[:digit:]]中都相同在哪種情況下它們是多余的,或與Posix類不同,在這種情況下,它們會使讀者感到困惑。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM