gpt4 book ai didi

c - 替代终端的 Bison/Flex 打印值

转载 作者:太空宇宙 更新时间:2023-11-04 01:03:06 25 4
gpt4 key购买 nike

我写了一个简单的语法:

operations :
/* empty */
| operations operation ';'
| operations operation_id ';'
;

operation :
NUM operator NUM
{
printf("%d\n%d\n",$1, $3);
}
;

operation_id :
WORD operator WORD
{
printf("%s\n%s\n%s\n",$1, $3, $<string>2);
}
;

operator :
'+' | '-' | '*' | '/'
{
$<string>$ = strdup(yytext);
}
;

如您所见,我定义了一个 operator 来识别 4 个符号之一。现在,我想在 operation_id 中打印这个符号。问题是,operator 中的逻辑仅适用于 alternative 中的最后一个符号。因此,如果我写 a/b;,它会打印出 ab/,这很酷。但是对于其他操作,例如。 a+b; 它打印aba。我做错了什么?

*我在示例输出中省略了新行符号。

最佳答案

你语法中的这个非终结符完全是错误的。

operator :
'+' | '-' | '*' | '/' { $<string>$ = strdup(yytext); }
;

首先,在yacc/bison中,每个产生式都有一个 Action 。该规则有四个产生式,其中只有最后一个具有关联的 Action 。这样写会更清楚:

operator : '+' 
| '-'
| '*'
| '/' { $<string>$ = strdup(yytext); }
;

这使得该操作仅适用于 token '/' 的减少更加明显。 .

Action 本身也不正确。 yytext不应该在 lexer 操作之外使用,因为它的值不可靠;它将是执行最近的词法分析器操作时的值,但由于解析器通常(但不总是)提前读取一个标记,因此它通常(但不总是)是与 下一个<相关联的字符串/em> token 。这就是为什么通常的建议是复制 yytext 的原因。 , 但想法是将其复制在词法分析器规则中,将副本分配给 yylval 的适当成员以便解析器可以使用 token 的语义值。

您应该避免使用 $<type>$ = .一个非终端只能有一种类型,它应该在 bison 文件的序言中声明:

 %type <string> operator

最后,你会发现拥有一个识别不同运算符的非终结符很少有用,因为不同的运算符在语法上是不同的。在更完整的表达式语法中,您需要区分 a + b * c ,它是 a 与 b 和 c 的乘积之和,以及 a * b + c ,它是 c 与 a 和 b 的乘积之和。这可以通过对求和和乘积语法使用不同的非终结符,或者对非终结符表达式使用不同的产生式并使用优先规则消除歧义来完成,但在这两种情况下,您都无法使用 operator。产生 + 的非终端和 *不分青红皂白。

关于它的值(value),这里解释为什么 a+b导致输出 aba :

  1. 制作operator : '+'没有明确的操作,所以它最终使用默认操作,即 $$ = $1 .

  2. 但是,返回 '+' 的词法分析器规则(大概——我在这里猜测)永远不会设置 yylval .所以yylval仍然具有上次分配的值。

  3. 据推测(另一个猜测),生成 WORD 的词法分析器规则正确设置 yylval.string = strdup(yytext); .所以 '+' 的语义值token是前面WORD的语义值 token ,也就是说指向字符串 "a" 的指针.

  4. 所以当规则

    operation_id :
    WORD operator WORD
    {
    printf("%s\n%s\n%s\n",$1, $3, $<string>2);
    }
    ;

执行,$1$2两者的值都是 "a" (指向同一个字符串的两个指针)和$3具有值 "b" .

很明显,$2 在语义上是不正确的具有值 "a" , 但还有另一个错误等待发生。正如所写,您的解析器泄漏内存,因为您从不 free() strdup 创建的任何字符串.这不是很令人满意,在某些时候您会想要修复这些操作,以便在不再需要语义值时释放它们。到那时,您会发现有两个语义值指向同一个已分配内存块很可能 free()将在同一个内存块上被调用两次,这是未定义的行为(并且可能会产生非常难以诊断的错误)。

关于c - 替代终端的 Bison/Flex 打印值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30742906/

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