在lex中识别关键字对
我正在尝试为一种文件类型编写解析器,这种文件使用的是成对的关键字(用空格分隔),但我在正确的实现方式上遇到了一些困难。一些可能的标记示例如下:
angle spring
angle dampen
angle collision
此外,还有块定义和结束该块的标记,例如:
dynamics
angle spring 1.0
angle dampen 0.0
angle collision 0.0
some 1 2 3
more ['stuff' 'here']
tokens "values can be strings, paths, etc"
end dynamics
换行符似乎很重要,我一直在利用它来判断我是在查看关键字还是普通字符串(关键字应该是每行的第一个标记)。我这样做是否正确?我是否应该直接将所有内容进行标记化,并在yacc阶段更严格地定义成对的关键字?
谢谢你的时间!
1 个回答
4
问题在于,你把本来应该看作一个整体的东西,分成了多个部分。如果一个关键字里面有空格,那就说明这些空格也是这个关键字的一部分。
如果你在定义关键字的时候把空格也包括进去,那么在解析的时候就不需要单独处理这些空格了。这意味着你应该把关键字的匹配和普通标识符的匹配分开来处理。
举个例子:
from ply.lex import TOKEN
KEYWORDS = [
r'some', r'keyword',
r'keyword with token',
r'other keyword',
]
keyword = '|'.join(keyword.replace(' ', '\s+') for keyword in KEYWORDS)
@TOKEN(keyword)
def t_KEYWORD(t):
# remove spaces
value = ''.join(x for x in t.value if not x.isspace())
return value.upper()
注意那行 @TOKEN(keyword)
:你可以通过 TOKEN
装饰器动态设置函数的文档字符串。这允许你使用复杂的正则表达式来定义关键字,即使定义它们“需要”使用表达式,而不是简单的字符串。
另一种方法是把用空格分开的关键字当作多个关键字来处理。所以你可以保留通常的标识符和关键字的定义,并修改你的语法来使用多个关键字,而不是一个。
比如你可以有这样的语法规则:
def p_dynamics(p):
'DYNAMICS BLOCK END DYNAMICS'
而不是:
def p_dynamics(p):
'DYNAMICS BLOCK END_DYNAMICS'
根据你的限制条件,有一种解决方案可能更容易实现。