2011-02-16 93 views
6

我將ply用作我的lex解析器。我的規格如下:Ply Lex解析問題

t_WHILE = r'while' 
t_THEN = r'then' 
t_ID = r'[a-zA-Z_][a-zA-Z0-9_]*' 
t_NUMBER = r'\d+' 
t_LESSEQUAL = r'<=' 
t_ASSIGN = r'=' 
t_ignore = r' \t' 

當我嘗試解析以下字符串:

"while n <= 0 then h = 1" 

它提供了以下的輸出:

LexToken(ID,'while',1,0) 
LexToken(ID,'n',1,6) 
LexToken(LESSEQUAL,'<=',1,8) 
LexToken(NUMBER,'0',1,11) 
LexToken(ID,'hen',1,14)  ------> PROBLEM! 
LexToken(ID,'h',1,18) 
LexToken(ASSIGN,'=',1,20) 
LexToken(NUMBER,'1',1,22) 

它不那麼識別令牌,相反,它需要「母雞」作爲標識符。

任何想法?

+0

好的,我發現了這個問題。 – Karan 2011-02-16 21:36:42

回答

7

這個不起作用的原因與優先級匹配令牌的方式有關,最長的令牌正則表達式首先被測試。

防止此問題的最簡單方法是匹配相同類型的標識符和保留字,並根據匹配選擇適當的標記類型。以下代碼是在ply documentation

import ply.lex 

tokens = [ 'ID', 'NUMBER', 'LESSEQUAL', 'ASSIGN' ] 
reserved = { 
    'while' : 'WHILE', 
    'then' : 'THEN' 
} 
tokens += reserved.values() 

t_ignore = ' \t' 
t_NUMBER = '\d+' 
t_LESSEQUAL = '\<\=' 
t_ASSIGN = '\=' 

def t_ID(t): 
    r'[a-zA-Z_][a-zA-Z0-9_]*' 
    if t.value in reserved: 
     t.type = reserved[ t.value ] 
    return t 

def t_error(t): 
    print 'Illegal character' 
    t.lexer.skip(1) 

lexer = ply.lex.lex() 
lexer.input("while n <= 0 then h = 1") 
while True: 
    tok = lexer.token() 
    if not tok: 
     break 
    print tok 
4

PLY類似於示例優先聲明爲根據最長的正則表達式簡單的字符串的令牌,但聲明爲函數的令牌具有它們的順序優先級。

從文檔:

當建立主正則表達式,規則在 加入順序如下:

  1. 通過函數定義的所有令牌以相同的順序加入,因爲它們出現在詞法分析器文件中。
  2. 按字符串定義的令牌按照正則表達式長度遞減的順序進行排序(首先添加更長的表達式 )。

因此,另一種解決辦法是簡單地指定要優先考慮爲功能標記,而不是字符串,像這樣:

def t_WHILE(t): r'while'; return t 
def t_THEN(t): r'then'; return t 
t_ID = r'[a-zA-Z_][a-zA-Z0-9_]*' 
t_NUMBER = r'\d+' 
t_LESSEQUAL = r'<=' 
t_ASSIGN = r'=' 
t_ignore = ' \t' 

這樣一段時間,然後將率先規則被添加,你會得到你期望的行爲。

請注意,您對t_ignore使用r' \t'(原始字符串),因此Python將\視爲反斜槓。它應該是一個簡單的字符串,如上例所示。