我试图为使用关键字对(以空格分隔)的文件类型编写解析器,并且正在努力使用正确的方法来执行此操作。令牌的一些示例可能是:
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阶段,我是否应该只是标记化所有内容并更严格地定义对?
谢谢你的时间!
答案 0 :(得分:3)
问题在于您尝试将逻辑上的单个标记视为多个标记。如果关键字包含空格,则表示空格是关键字标记的一部分。
如果您定义关键字标记,包括您在解析器中无需处理它们的空格。这意味着您应该将关键字匹配与普通标识符匹配进行划分。
例如:
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
装饰器动态设置函数的docstring。这允许复杂的正则表达式用于定义令牌,即使定义它们"需要"使用表达式而不是简单的字符串文字。
另一种方法是将空格分隔的关键字视为多个关键字。因此,您保留标识符和关键字的通常定义,并修改语法以使用多个关键字而不是一个。
例如,您的语法规则如下:
def p_dynamics(p):
'DYNAMICS BLOCK END DYNAMICS'
而不是:
def p_dynamics(p):
'DYNAMICS BLOCK END_DYNAMICS'
根据具体情况,您可以更轻松地实施一个解决方案。