【发布时间】:2014-03-13 06:40:28
【问题描述】:
我正在开发的 DSL 允许用户定义一个“完整的文本替换”变量。在解析代码时,我们需要查找变量的值并从该代码重新开始解析。
替换可以是非常简单的(单个常量)或整个语句或代码块。 这是一个模拟语法,我希望能说明我的观点。
grammar a;
entry
: (set_variable
| print_line)*
;
set_variable
: 'SET' ID '=' STRING_CONSTANT ';'
;
print_line
: 'PRINT' ID ';'
;
STRING_CONSTANT: '\'' ('\'\'' | ~('\''))* '\'' ;
ID: [a-z][a-zA-Z0-9_]* ;
VARIABLE: '&' ID;
BLANK: [ \t\n\r]+ -> channel(HIDDEN) ;
那么下面连续执行的语句应该是有效的;
SET foo = 'Hello world!';
PRINT foo;
SET bar = 'foo;'
PRINT &bar // should be interpreted as 'PRINT foo;'
SET baz = 'PRINT foo; PRINT'; // one complete statement and one incomplete statement
&baz foo; // should be interpreted as 'PRINT foo; PRINT foo;'
每当发现 & 变量标记时,我们立即切换到解释该变量的值。如上所述,这可能意味着您以一种无效的方式设置代码,其中充满了仅在值恰到好处时才完成的半语句。可以在文本中的任何位置重新定义变量。
严格来说,当前的语言定义并没有不允许在彼此内部嵌套 &var,但当前的解析无法处理这个问题,如果不允许,我也不会感到不安。
目前我正在使用访问者构建一个解释器,但我坚持使用这个。
我怎样才能构建一个词法分析器/解析器/解释器来允许我这样做?感谢您的帮助!
【问题讨论】:
-
在你的语法中,这是一些令人讨厌的诡计。在单个
entry中可以出现VARIABLEs 的位置和数量是否有任何限制?我的意思是,这是否允许:SET a = 'P'; SET b = 'R'; SET c = 'I'; SET d = 'N'; SET e = 'T'; SET f = ' '; SET g = ''''; SET h = 'ouch!'; SET i = ''''; SET j = ';'; &a&b&c&d&e&f&g&h&i&j最终评估PRINT 'ouch!';? -
是的,这确实是一个有效的声明:/ 我怀疑有人曾经这样使用它,但该应用程序已经存在多年,因此您永远无法确定客户做了什么。读取字符以组成标记时的当前实现只是切换到从变量值读取,但我不知道这是否/如何与 ANTLR 兼容。
-
我认为在解析过程中没有一种简单的方法可以插入代码/令牌。至少不使用提供的 API 类(您当然可以实现自己的
TokenStream并将其提供给解析器)。 -
如果你这样做
SET baz = '&baz'; &baz;会发生什么? -
3/ 您能否添加限制以禁止愚蠢的行为,例如不包含整个令牌的
&-vars 或set bob = set; &bob xyzzy = plugh;之类的东西 :-)
标签: parsing antlr interpreter antlr4 lexer