【发布时间】:2016-12-10 10:58:05
【问题描述】:
我已经进行了一些搜索,包括再看一遍我面前的红龙书,但我还没有找到明确的答案。大多数人都在谈论缩进方面的空白敏感性,但我不是这样。
我想为一种简单的语言实现转译器。这种语言有一个“命令”的概念,它是一个保留关键字,后跟一些参数。为了让您了解我在说什么,一系列命令可能看起来像这样:
print "hello, world!";
set running 1;
while running @
read progname;
launch progname;
print "continue? 1 = yes, 0 = no";
readint running;
@
非正式地,您可以将语法视为类似于
<program> ::= <statement> <program>
<statement> ::= while <expression> <sequence>
| <command> ;
<sequence> ::= @ <program> @
| <statement>
<command> ::= print <expression>
| set <variable> <expression>
| read <variable>
| readint <variable>
| launch <expression>
<expression> ::= <variable>
| <string>
| <int>
为简单起见,我们可以这样定义以下内容
<string> is an arbitrary sequence of characters surrounded by quotes
<int> is a sequence of characters '0'..'9'
<variable> is a sequence of characters 'a'..'z'
现在这通常不会有任何问题。事实上,只要这个规范,我就有一个工作实现,其中词法分析器默默地吃掉所有的空白。然而,这里有一个问题:
命令的参数必须用空格分隔!
也就是说,写应该是违法的
while running@print"hello";@
尽管就语法而言,这显然不是模棱两可的。关于如何解决这个问题,我有两个想法。
每当消耗一些空格时输出一个标记,并在语法中包含空格。我怀疑这会使语法变得更加复杂。
-
重写语法,而不是“硬编码”每个命令的参数,我有一个“参数”的生产规则来处理空格。它可能看起来像
<command> ::= <cmdtype> <arguments> <arguments> ::= <argument> <arguments> <argument> ::= <expression> <cmdtype> ::= print | set | read | readint | launch然后我们可以确保词法分析器以某种方式 (?) 在遇到
<argument>标记时处理前导空格。但是,这会将处理内置命令的复杂性(除其他外?)的复杂性转移到解析器中。
这通常是如何解决的? 当一种语言的语法在特定的地方需要空格,但在其他地方几乎都是可选的,那么在词法分析器或解析器中处理它是否有意义?
我希望我能稍微修改一下语言的规范,因为这样会更容易实现,但不幸的是,这是一个向后兼容的问题,不可能。
【问题讨论】:
标签: parsing