2017-04-16 45 views
0

假設我想只有一個PLY令牌 - 'INTEGER'。不過,我希望能夠解析不同基地的典型C型文字,因此我希望能夠解析像0b10(或0B10),010100x10(或0X10)這樣的字符串。由於我並不在乎「輸入格式」是什麼,因此我只想在Python中使用int的值。如何組織使用PLY返回相同標記的多個函數?

但是,在單個函數中處理所有這4種情況並不是特別方便......首先或所有正則表達式變得相當長:r'0[0-7]+|0[bB][01]+|0[xX][0-9a-fA-F]+|[0-9]'。但是這是一個小問題 - 函數的代碼必須處理大量的組合以知道使用哪個基礎,因爲從0開始的字符串實際上只能是單個字符,因此需要檢查其他案例(下一個字符是xX,bB)也必須考慮長度。

所以我只是希望將它作爲4個單獨的函數,但都返回相同的'INTEGER'類型的令牌。我寧願不要引入BINARY_INTEGER,OCTAL_INTEGER,DECIMAL_INTEGERHEXADECIMAL_INTEGER,因爲這會不必要地使解析器複雜化(或者我可能會過度使用它?)。

我想知道是否有更聰明的做法,而不是強迫token.type'INTEGER'四個「免費」功能?以外的東西:

def t_BINARY_LITERAL(t): 
    r'0[bB][01]+' 
    t.value = int(t.value[2:], 2) 
    t.type = 'INTEGER' 
    return t 

def t_OCTAL_LITERAL(t): 
    r'0[0-7]+' 
    t.value = int(t.value[1:], 8) 
    t.type = 'INTEGER' 
    return t 

def t_DECIMAL_LITERAL(t): 
    r'[0-9]+' 
    t.value = int(t.value, 10) 
    t.type = 'INTEGER' 
    return t 

def t_HEXADECIMAL_LITERAL(t): 
    r'0[xX][0-9a-fA-F]+' 
    t.value = int(t.value[2:], 16) 
    t.type = 'INTEGER' 
    return t 

回答

2

明確設置t.type是正確的解決方案。如果你發現它是多餘的,你可以重構成一個轉換函數:

def send_int(t, offset, base): 
    t.value = int(t.value[offset:], base) 
    t.type = 'INTEGER' 
    return t 

def t_HEXADECIMAL_LITERAL(t): 
    r'0[xX][0-9a-fA-F]+' 
    return send_int(t, 2, 16) 

# etc. 
相關問題