Error: popping nterm
Error: popping nterm
我正在尝试理解 Flex 给出的诊断消息:
Entering state 5
Return for a new token:
Reading a token: Next token is token END_OF_FILE (4.0: )
Shifting token END_OF_FILE (4.0: )
Entering state 43
Reducing stack by rule 143 (line 331):
= nterm syntax (0.0-17: )
= nterm top_levels (0.18-4.0: )
= token END_OF_FILE (4.0: )
-> $$ = nterm s (0.0-4.0: )
Stack now 0
Entering state 3
Return for a new token:
Reading a token: Next token is token END_OF_FILE (4.0: )
4/0: syntax error
Error: popping nterm s (0.0-4.0: )
Stack now 0
Cleanup: discarding lookahead token END_OF_FILE (4.0: )
Stack now 0
我不明白为什么/它试图用 EOF 令牌做什么。以下是 Flex 规则:
<<EOF>> { return END_OF_FILE; }
野牛规则:
top_level : message
| enum
| service
| import { $$ = Py_None; }
| package { $$ = Py_None; }
| option_def { $$ = Py_None; }
| ';' { $$ = Py_None; } ;
top_levels : %empty { $$ = py_list(Py_None); }
| top_levels top_level { $$ = py_append(, ); } ;
s : syntax top_levels END_OF_FILE { $$ = ; } ;
而Bison生成的输出文件:
State 3
0 $accept: s . $end
$end shift, and go to state 6
State 5
142 top_levels: top_levels . top_level
143 s: syntax top_levels . END_OF_FILE
BOOL shift, and go to state 9
... bunch of similar rules
END_OF_FILE shift, and go to state 43
';' shift, and go to state 44
import go to state 45
... bunch of similar rules
top_level go to state 55
State 6
0 $accept: s $end .
$default accept
我不知道发生了什么。为什么它报告两次读取 EOF 令牌?弹出 s
到底有什么问题?对我来说,它似乎实际上接受了整个事情,然后决定拒绝它,因为它第二次将令牌变成红色......但整个报告非常混乱。
1。问题
不要这样做:
<<EOF>> { return END_OF_FILE; }
Yacc/bison 解析器使用内部规则扩充语法,该规则生成开始符号,后跟一个名为 $end
的内部 eof 标记,其标记编号为 0。(您可以在状态 3 中看到此规则和 6.) 这是语法中唯一的接受规则。
默认情况下,(f)lex 扫描仪 return 检测到 EOF 时为 0。这样一切就可以正常工作了。
当您尝试在 EOF 上发送不同的令牌时,您试图破坏此机制,但它不会起作用,因为开始符号不是接受规则。在减少起始符号后,解析器尝试减少 $accept
规则,因此它向扫描器询问另一个标记。但是扫描器已经命中了 EOF。在大多数情况下,扫描器将再次执行 <<EOF>>
操作(尽管不能保证),但这不会产生它需要的 $end
令牌。所以你得到一个语法错误。
2。潜在问题(可能)
通常,人们尝试这样做是为了创建一个用户操作,当输入被接受时 运行s,通常是为了 return 将解析结果 yyparse
的调用者通过一个“out”参数。尝试在开始生产中明确识别 EOF 令牌(甚至 $end
令牌)是行不通的,但有一个更简单的解决方案:一个额外的单元规则:
%start return
%%
return: s { *out = ; }
s: syntax top_levels { $$ = ; }
请注意,您也可以在没有 top_levels
的情况下执行此操作:
%start return
%%
return: { *out = ; }
s: syntax { $$ = py_list(Py_None); }
| s top_level { $$ = py_append(, ); }
另一种方法是在启动规则的操作中使用特殊的 YYACCEPT
操作宏。但是,我相信上面概述的标准解决方案更简单,因为它不需要扫描仪提供任何东西。
3。跟踪输出
Error: popping nterm s (0.0-4.0: )
表示:
检测到语法错误。
作为错误恢复的一部分,解析器从堆栈中弹出 non-terminal s
。
non-terminal 的源位置从 0.0 扩展到 4.0 (line . column
)
如果 s
(或其语义类型)有一个已注册的析构函数,那么在第 2 步将有 运行。您可能希望为引用 [=69 的语法类型注册析构函数=] 值以减少它们的引用计数,这样您就不会因语法错误而泄漏内存。但也许我错了。
此外,您可以为语法值注册一个 %printer
,在这种情况下,它将在冒号之后打印。
我正在尝试理解 Flex 给出的诊断消息:
Entering state 5
Return for a new token:
Reading a token: Next token is token END_OF_FILE (4.0: )
Shifting token END_OF_FILE (4.0: )
Entering state 43
Reducing stack by rule 143 (line 331):
= nterm syntax (0.0-17: )
= nterm top_levels (0.18-4.0: )
= token END_OF_FILE (4.0: )
-> $$ = nterm s (0.0-4.0: )
Stack now 0
Entering state 3
Return for a new token:
Reading a token: Next token is token END_OF_FILE (4.0: )
4/0: syntax error
Error: popping nterm s (0.0-4.0: )
Stack now 0
Cleanup: discarding lookahead token END_OF_FILE (4.0: )
Stack now 0
我不明白为什么/它试图用 EOF 令牌做什么。以下是 Flex 规则:
<<EOF>> { return END_OF_FILE; }
野牛规则:
top_level : message
| enum
| service
| import { $$ = Py_None; }
| package { $$ = Py_None; }
| option_def { $$ = Py_None; }
| ';' { $$ = Py_None; } ;
top_levels : %empty { $$ = py_list(Py_None); }
| top_levels top_level { $$ = py_append(, ); } ;
s : syntax top_levels END_OF_FILE { $$ = ; } ;
而Bison生成的输出文件:
State 3
0 $accept: s . $end
$end shift, and go to state 6
State 5
142 top_levels: top_levels . top_level
143 s: syntax top_levels . END_OF_FILE
BOOL shift, and go to state 9
... bunch of similar rules
END_OF_FILE shift, and go to state 43
';' shift, and go to state 44
import go to state 45
... bunch of similar rules
top_level go to state 55
State 6
0 $accept: s $end .
$default accept
我不知道发生了什么。为什么它报告两次读取 EOF 令牌?弹出 s
到底有什么问题?对我来说,它似乎实际上接受了整个事情,然后决定拒绝它,因为它第二次将令牌变成红色......但整个报告非常混乱。
1。问题
不要这样做:
<<EOF>> { return END_OF_FILE; }
Yacc/bison 解析器使用内部规则扩充语法,该规则生成开始符号,后跟一个名为 $end
的内部 eof 标记,其标记编号为 0。(您可以在状态 3 中看到此规则和 6.) 这是语法中唯一的接受规则。
默认情况下,(f)lex 扫描仪 return 检测到 EOF 时为 0。这样一切就可以正常工作了。
当您尝试在 EOF 上发送不同的令牌时,您试图破坏此机制,但它不会起作用,因为开始符号不是接受规则。在减少起始符号后,解析器尝试减少 $accept
规则,因此它向扫描器询问另一个标记。但是扫描器已经命中了 EOF。在大多数情况下,扫描器将再次执行 <<EOF>>
操作(尽管不能保证),但这不会产生它需要的 $end
令牌。所以你得到一个语法错误。
2。潜在问题(可能)
通常,人们尝试这样做是为了创建一个用户操作,当输入被接受时 运行s,通常是为了 return 将解析结果 yyparse
的调用者通过一个“out”参数。尝试在开始生产中明确识别 EOF 令牌(甚至 $end
令牌)是行不通的,但有一个更简单的解决方案:一个额外的单元规则:
%start return
%%
return: s { *out = ; }
s: syntax top_levels { $$ = ; }
请注意,您也可以在没有 top_levels
的情况下执行此操作:
%start return
%%
return: { *out = ; }
s: syntax { $$ = py_list(Py_None); }
| s top_level { $$ = py_append(, ); }
另一种方法是在启动规则的操作中使用特殊的 YYACCEPT
操作宏。但是,我相信上面概述的标准解决方案更简单,因为它不需要扫描仪提供任何东西。
3。跟踪输出
Error: popping nterm s (0.0-4.0: )
表示:
检测到语法错误。
作为错误恢复的一部分,解析器从堆栈中弹出 non-terminal
s
。non-terminal 的源位置从 0.0 扩展到 4.0 (
line . column
)
如果 s
(或其语义类型)有一个已注册的析构函数,那么在第 2 步将有 运行。您可能希望为引用 [=69 的语法类型注册析构函数=] 值以减少它们的引用计数,这样您就不会因语法错误而泄漏内存。但也许我错了。
此外,您可以为语法值注册一个 %printer
,在这种情况下,它将在冒号之后打印。