【发布时间】:2020-02-03 23:30:50
【问题描述】:
我正在尝试使用他们的官方grammar description 语言为 MAXScript 语言创建解析器。我使用 flex 和 bison 来创建词法分析器和解析器。
但是,我遇到了以下问题。在传统语言(例如 C)中,语句由特殊标记(C 中的;)分隔。但在 MAXScript 中,复合表达式内的表达式可以用; 或newline 分隔。还有其他语言在其解析器中使用空格字符,例如 Python。但是Python对newline的放置要严格得多,Python中的以下程序无效:
# compile error
def
foo(x):
print(x)
# compile error
def bar
(x):
foo(x)
但是在 MAXScript 中以下程序是有效的:
fn
foo x =
( // parenthesis start the compound expression
a = 3 + 2; // the semicolon is optional
print x
)
fn bar
x =
foo x
你甚至可以这样写:
for
x
in
#(1,2,3,4)
do
format "%," x
这将评估罚款并将1,2,3,4, 打印到输出。所以newlines 可以插入很多地方,没有特殊意义。
但是,如果您像这样在程序中再插入一个newline:
for
x
in
#(1,2,3,4)
do
format "%,"
x
您将收到运行时错误,因为format 函数需要传递多个参数。
这是我拥有的野牛输入文件的一部分:
expr:
simple_expr
| if_expr
| while_loop
| do_loop
| for_loop
| expr_seq
expr_seq:
"(" expr_semicolon_list ")"
expr_semicolon_list:
expr
| expr TK_SEMICOLON expr_semicolon_list
| expr TK_EOL expr_semicolon_list
if_expr:
"if" expr "then" expr "else" expr
| "if" expr "then" expr
| "if" expr "do" expr
// etc.
这将仅解析仅使用newline 作为表达式分隔符的程序,并且不会期望newlines 分散在程序的其他地方。
我的问题是:有没有办法告诉野牛将令牌视为可选令牌?对于野牛,这意味着:
- 如果您找到
newline令牌并且您可以使用它进行转换或减少,那么就这样做。 - 否则只需丢弃
newline令牌并继续解析。
因为如果没有办法做到这一点,我能想到的唯一其他解决方案是修改野牛语法文件,以便它在任何地方都需要那些newlines。并提高 newline 充当表达式分隔符的规则的优先级。像这样:
%precedence EXPR_SEPARATOR // high precedence
%%
// w = sequence of whitespace tokens
w: %empty // either nothing
| TK_EOL w // or newline followed by other whitespace tokens
expr:
w simple_expr w
| w if_expr w
| w while_loop w
| w do_loop w
| w for_loop w
| w expr_seq w
expr_seq:
w "(" w expr_semicolon_list w ")" w
expr_semicolon_list:
expr
| expr w TK_SEMICOLON w expr_semicolon_list
| expr TK_EOL w expr_semicolon_list %prec EXPR_SEPARATOR
if_expr:
w "if" w expr w "then" w expr w "else" w expr w
| w "if" w expr w "then" w expr w
| w "if" w expr w "do" w expr w
// etc.
但是这看起来很丑陋且容易出错,如果可能的话,我想避免这样的解决方案。
【问题讨论】: