[英]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)*
在該正則表達式中, alpha
和digit
只是普通字符串,因此與[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.