2014-10-27 68 views
1

我正在尝试为利用关键字对(由空格分隔)的文件类型编写解析器,并且正在以正确的方式挣扎。令牌的一些例子可能是:确定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阶段将所有内容标记为一对并更严格地定义配对?

谢谢你的时间!

+0

我不明白问题在哪里。标记时只需使用正则表达式'angle \ spring',并且解析器不需要知道它实际上使用了空格。如果间距可以是任意的,你可以使用像'angle \ s + spring'这样的正则表达式来定义关键词标记。如果这不是你想要的,你应该用一个例子来澄清你的意思。 – Bakuriu 2014-10-27 20:22:23

+1

我遵循ply文档(http://www.dabeaz.com/ply/ply.html,4.3标记规范)中描述的保留关键字示例,该示例在决定它是只是一个字符串。我想为所有使用空格的令牌创建特殊规则? – spencewah 2014-10-27 20:26:02

回答

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装饰设置功能的文档字符串。这允许使用复杂的正则表达式来定义令牌,即使将它们定义为“需要”使用表达式而不是简单的字符串文字。


另一种方法是将空格分隔的关键字视为多个关键字。所以你保留标识符和关键字的通常定义,并修改你的语法来使用多个关键字而不是一个。

例如你有一个语法规则,如:

def p_dynamics(p): 
    'DYNAMICS BLOCK END DYNAMICS' 

代替:

def p_dynamics(p): 
    'DYNAMICS BLOCK END_DYNAMICS' 

取决于你有一个解决方案可能是更容易实现的约束上。