- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 bison 从我无法控制的规范中解析 lang。在它的定义中有一个递归规则,并且由于该语言使用缩进,这导致了减少/减少错误。所以为了摆脱减少/减少我添加了一个分号。我有一个布局跟踪器,它已经自动插入分号和大括号。我正在考虑扩展插入分号的规则以支持我添加的不在规范中的规则,但我想不出一种方法来知道我们何时处于递归规则的末尾。
是否有可靠的方法知道我何时处于递归规则的末尾或关于不同方法的任何建议?或者像它一样困惑是否有某种方法可以在解析器和词法分析器之间进行双向通信?
目前正在使用拉式解析器。我认为使用推送解析器可以让我更好地跟踪我在词法分析器中的位置,但是当我尝试使用 define 指令生成推送解析器时,该选项无法识别。我使用带有自定义词法分析器的 bison 3.0.4,使用 C++ api 生成纯解析器。
编辑:
exp : infixexp TYPE_SEP type {}
| infixexp TYPE_SEP context RIGHT_ARROW type {}
| infixexp {}
infixexp : lexp qop infixexp {}
| MINUS infixexp {}
| lexp {}
lexp : BACKSLASH apat_list FUNC_TYPE_CONS exp {}
| KW_LET decls KW_IN exp {}
| KW_IF exp SEMI_COLON KW_THEN exp SEMI_COLON KW_ELSE exp {} //conditional
| KW_CASE exp KW_OF L_BRACE alts R_BRACE {}
| KW_DO L_BRACE stmts R_BRACE {}
| fexp SEMI_COLON {}
fexp : aexp {}
| fexp aexp {}
literal : INTEGER {}
| FLOAT {}
| CHAR {}
| STRING {}
aexp : qvar {}
| gcon {}
| literal
| L_PAREN exp R_PAREN {}
| L_PAREN exp_list R_PAREN {}
| L_BRACKET exp R_BRACKET {}
| L_BRACKET exp_list R_BRACKET {}
| L_BRACKET exp DOTDOT R_BRACKET {}
| L_BRACKET exp DOTDOT exp R_BRACKET {}
| L_BRACKET exp COMMA exp DOTDOT exp R_BRACKET {}
| L_BRACKET exp PIPE qual_list R_BRACKET {}
| L_PAREN infixexp qop R_PAREN {}
| L_PAREN qop infixexp R_PAREN {}
| qcon L_BRACE fbind_list R_BRACE {}
| aexp L_BRACE fbind_list R_BRACE {}
apat : qvar {}
| qvar AT_SYM apat {}
| gcon {}
| qcon L_BRACE fpat_list R_BRACE {}
| literal {}
| WILDCARD {}
| L_PAREN pat R_PAREN {}
| L_PAREN pat COMMA pat_list R_PAREN {}
| L_BRACKET pat_list R_BRACKET {}
| TILDE apat {}
添加了语法部分。它基本上是 Haskell 2010 规范的修改版本。通过在 lexp
的定义中的 fexp
之后添加分号解决了 reduce/reduce 冲突。
我正在模拟缩进/缩进并插入左括号和花括号。我基本上在想 the lexer hack但无法弄清楚如何与 Bison 一起做。并且有多个递归规则,但只有一个导致减少/减少错误。
编辑 2:
最佳答案
处理缩进感知语言的常用方法是在词法扫描器中制造 INDENT 和 DEDENT 标记。使用推送接口(interface)会更容易,因此很遗憾您使用的是未实现该功能的 bison C++ API。
但也可以在词法扫描器和解析器之间使用垫片来轻松完成。您可以在 this answer 中查看 Python shim 的示例。 ; ply
也不提供推送解析器接口(interface),因此 shim 保留一个小的持久 token 队列,这些 token 将被发送到解析器并在向真正的词法扫描器询问下一个 token 之前检查该队列。
正如该答案所表明的,在大多数布局感知语言中,并非所有换行符实际上都具有语义意义。例如,在 Python 本身中,圆括号、大括号或方括号内的换行符只是普通的空格。 shim 也可以很容易地实现该规则(尽管我没有通过在链接的答案中这样做而使代码复杂化),只需跟踪括号的级别即可。
并非所有语言都让生活变得如此轻松;例如,您可能有一种语言,由于存在函数文字,缩进可以在括号列表中重新声明自己。或者你可能有一种像 ecmascript 这样的语言,如果替代解析不可能,其中分号插入规则允许甚至在括号之外的行上运行。 Haskell 有类似的规则,如果无法进行替代解析,则可以插入大括号。
起草 ecmascript 规则的目的是使编写解析器成为可能。 (或者,更准确地说,我认为该规则是通过对现有解析器进行逆向工程而起草的,但我无法证明这一点。)事实证明,可以通过构造字典来实现 ecmascript 自动分号插入可以用换行符分隔而无需插入分号的标记对。 (或者,或者,如果可能的话,必须在它们之间插入分号的成对标记,这是另一个集合的倒数。)这些集合可以通过语法分析自动构建,使用每个产生式的 FIRST 和 FOLLOW 集合。 (ecmascript 规则的细节需要做一些调整,因为有一些标记对可以出现在一个有效的程序中,但不允许用换行符分隔。例如,return 3
是一个有效的语句,但如果 return
在一行的末尾并且 3 在下一行,则必须自动插入一个分号')。 Bison 不会自动执行此分析,因此它依赖于自定义工具,但这并不是特别困难。
Haskell 似乎并不那么随和。我在 Haskell report, section 9.3 中看到, 在该部分的末尾:
The parse-error rule is hard to implement in its full generality, because doing so involves fixities. For example, the expression
do a == b == c
has a single unambiguous (albeit probably type-incorrect) parse, namely
(do { a == b }) == c
because (==) is non-associative. Programmers are therefore advised to avoid writing code that requires the parser to insert a closing brace in such situations.
这不是很有希望,但它也表明实现不会是完美的,并且恳请程序员不要期望完美的解析器实现:)
我认为将链接答案中的 IndentWrapper
shim 翻译成 C++ 并不困难,即使对于不太熟悉 Python 的人来说也是如此,所以我没有费心在这里做。如果该假设不正确,请告诉我。
关于c++ - Bison 获取下一个可能的标记或确定正在尝试的规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34540653/
我有一个使用 Yacc 编写的语法。语法的相关部分摘录在这里 postfix : primary | postfix '[' expr ']' | postfix '[' ex
如何在 bison/yacc 中使用继承的属性? 说,我有这样的语法 - 程序 -> stmts 我想做的是在 Bison 身上: 程序:stmts {$$.next = newLabel(); $1
有什么方法可以更改 Bison 错误消息的格式?例如,不要说 syntax error, unexpected T_ID, expected ';' or T_IMPORT说 unexpected i
我的语法有这两个标记声明: %token RP %token ELSE 而这两条规则: Statement : IF LP Exp RP Statement; Statement : IF LP
如果有一个表单的输入文件: BEGIN stuff.... END BEGIN stuff ... END 我的 .y 文件是这样的 %token BEGIN %token END %star
我希望为现有语言创建一个 JavaScript 解析器,该语言目前具有笨拙的“手工制作”C# 和 Java 解析器。我想使用 Jison,并且也一直在尝试学习 Bison 的基础知识。 我不确定如何回
目前我正在研究一个源到源编译器,我已经编写了一个野牛解析器,可以正确地为输入创建 AST。我现在需要对语法树进行多次转换,因此我需要向树中插入许多节点。 我可以手动创建所有要添加到语法树中的结构体/联
如果有一个表单的输入文件: BEGIN stuff.... END BEGIN stuff ... END 我的 .y 文件是这样的 %token BEGIN %token END %star
我正在寻找为现有语言创建 JavaScript 解析器的方法,该语言目前具有笨拙的“手工制作”C# 和 Java 解析器。想用Jison,也在努力学习Bison的基础。 一个我不确定如何回答的问题是
我正在使用 flex/bison 编写解析器(我可以用 Python 编写解析器,但我总是更喜欢经典。) 当我用这个编译代码时: gcc -lfl -ly chance.tab.c lex.yy.c
正在使用 flex/bison 开发编译器。我的构建输出中有此警告。 警告:在默认操作中键入冲突 ('s' '') 请问有什么帮助吗? 最佳答案 它似乎与源中的 %token 和 %type 声明有关
考虑这个 lex.l 文件: %{ #include "y.tab.h" %} digit [0-9] letter [a-zA-Z] %% "+"
我正在为 bison 中的一个简单的 Pascal 编译器编写语法,我想可视化我在 pascal.y 中指定的语法的解析树。是否可以基于我的 pascal.y 文件以图形方式显示语法树? 最佳答案 野
我正在尝试编写一个能够使用以下输入的语法: begin #this is a example x = 56; while x > 0 do begin point 15
我正在尝试使用 BNF 语法编写 Flex/Bison 文件。但是,当我尝试编译时出现错误,而且我不确定如何调试它们。 BNF语法: ::= | head() ::=:: | @ | tail() |
我正在用 Flex/Bison 编写一个小程序来标记/解析我创建的查询语言。 我想知道是否有任何方法可以在 Flex/Bison 中创建任何关键字。 我的意思是:flex 将输入分解成一个标记列表,但
我正在尝试使用 flex 和 bison 创建过滤器,因为我想从复杂的语言中获取某些语法元素。我的计划是使用 flex + bison 来识别语法,并转储出感兴趣元素的位置。 (然后使用脚本根据转储的
我正在尝试实现一个可以进行浮点运算的 Flex/bison 计算器。我的 Flex 代码如下所示 %{ #include "calc.tab.h" #include void yyerror(cha
我正在尝试使用 FLEX 和 BISON 进行一些练习。 这是我写的代码: calc_pol.y %{ #define YYSTYPE double #include "calc_pol.tab.h"
我有一个使用括号和方括号作为分隔符的语法。当由 bison 生成的解析器输入带有不平衡分隔符的输入时,传递给 yyerror 的 YYLTYPE* 中的错误位置是输入的结尾。所以,例如,在输入 x
我是一名优秀的程序员,十分优秀!