0

In my lexer & parser by ocamllex and ocamlyacc, I have a .mly as follows:

%{
  open Params
  open Syntax
%}

main:
| expr EOF { $1 }

expr:
| INTEGER { EE_integer $1 }
| LBRACKET expr_separators RBRACKET { EE_brackets (List.rev $2) }

expr_separators:
  /* empty */  { [] }
| expr         { [$1] }
| expr_separators ...... expr_separators { $3 :: $1 }

In params.ml, a variable separator is defined. Its value is either ; or , and set by the upstream system.

In the .mly, I want the rule of expr_separators to be defined based on the value of Params.separator. For example, when params.separtoris ;, only [1;2;3] is considered as expr, whereas [1,2,3] is not. When params.separtoris ,, only [1,2,3] is considered as expr, whereas [1;2;3] is not.

Does anyone know how to amend the lexer and parser to realize this?

PS:

The value of Params.separator is set before the parsing, it will not change during the parsing.

At the moment, in the lexer, , returns a token COMMA and ; returns SEMICOLON. In the parser, there are other rules where COMMA or SEMICOLON are involved.

I just want to set a rule expr_separators such that it considers ; and ignores , (which may be parsed by other rules), when Params.separator is ;; and it considers , and ignore ; (which may be parsed by other rules), when Params.separator is ,.

4

1 回答 1

0

在某些方面,此请求本质上与要求宏预处理器在运行时更改其替换,或要求编译器更改变量的类型相同。与程序本身一样,一旦语法被编译(无论是可执行代码还是解析表),就无法返回并修改它。至少,大多数 LR(k) 解析器生成器都是这种情况,它们产生确定性解析器。

此外,配置参数的唯一区别似乎不太可能是选择单个分隔符标记。如果未选择的分隔符标记“可能被其他规则解析”,那么当它是选择的分隔符标记时,它可能被那些其他规则解析,除非配置设置也导致那些其他规则被抑制。因此,至少,您似乎会看到以下内容:

expr : general_expr
expr_list : expr
%if separator is comma
expr : expr_using_semicolon
expr_list : expr_list ',' expr
%else
expr : expr_using_comma
expr_list : expr_list ';' expr
%endif

如果对您要实现的目标没有更具体的想法,我可以提供的最佳建议是您编写两个语法并根据配置设置选择在运行时使用哪个语法。大概这两种语法大多相似,因此您可能可以使用自己定制的预处理器从相同的输入文本生成它们,这可能看起来有点像上面的例子。(您可以使用m4通用宏处理器,但您可能会觉得对于这样一个简单的应用程序来说学习曲线太陡了。)

生成通用解析器的解析器生成器可以更轻松地进行运行时动态修改;许多这样的解析器生成器具有可以做到这一点的机制(尽管它们不一定是有效的机制)。例如,Bison 工具可以生成 GLR 解析器,在这种情况下,您可以使用谓词操作选择或取消选择特定规则。OCAML GLR 生成器 Dypgen 允许在解析期间将规则集动态添加到语法中。(我从未使用过 dypgen,但我一直想尝试一下;它看起来很有趣。)还有很多其他的。

在一些 GLR 解析器中使用过动态解析功能后,我只能说我的个人经历有点复杂。在运行时修改语法是一项脆弱的技术。语法往往不太容易拆分成独立的部分,因此修改语法规则可能会在您不希望受到影响的地方产生意想不到的后果。您并不总是确切地知道您的解析接受哪种语言,因为动态修改可能难以预测。等等。如果您尝试这种技术,我的建议是从最简单的修改开始,并在语法测试中投入更多精力(无论如何,这总是一个好主意)。

于 2020-08-22T02:45:26.197 回答