2014-10-27 70 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' 

取決於你有一個解決方案可能是更容易實現的約束上。