gpt4 book ai didi

c++ - Yacc 语法产生不正确的终端

转载 作者:行者123 更新时间:2023-11-28 06:11:14 25 4
gpt4 key购买 nike

我一直在研究一个业余编译器,在解析阶段使用 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:
...


%%

我无法弄清楚控制流代码可以使符号如何:规则匹配 lex 定义中未归类为符号的内容:

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

非常感谢了解 yacc 和一般语法的人提供的任何帮助。如有必要,还可以显示它解析的语法示例文件。

谢谢!

最佳答案

您不能指望 flex 操作之外的 yytext 的值。

Bison 语法通常在决定如何继续之前读取先行标记,因此在 bison 操作中,yytext 已被替换为先行标记的标记值。 (不过,您也不能指望这一点:有时不需要先行标记。)

因此,您需要在 flex 操作返回之前制作 yytext 的拷贝,并通过将其放入 yylval 语义 union 中使该拷贝可用于 bison 语法。

查看此 bison FAQ entry


顺便说一下,您的 flex 文件中的以下片段是不正确的:

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

在那个正则表达式中,alphadigit只是普通的字符串,所以和[a-zA-Z_]+("alpha "|"digit")*,这意味着它将匹配,例如,a_digitdigitdigit 但不匹配 a_123。 (它会匹配 a_digitdigitdigit 而不是 + 之后的部分,所以我认为这不是您的意图。)

总的来说,我认为使用 Posix 字符类比手写字符类或定义的符号更好,所以我会这样写

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

假设您的意图是一个符号可以以下划线开头但不能以下划线结尾,并且可以以数字结尾但不能以数字开头。使用 Posix 字符类要求您使用正确的语言环境执行 flex——几乎可以肯定是 C 语言环境——但是字符范围也是如此,所以使用自文档化的 Posix 类不会有任何损失.

(当然,我不知道你对 {alpha}{digit} 的定义是什么,但在我看来它们要么是相同的[[:alpha:]][[:digit:]],在这种情况下它们是多余的,或者与 Posix 类不同,在这种情况下它们令人困惑给读者。)

关于c++ - Yacc 语法产生不正确的终端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31224507/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com