[英]ambiguity in parsing comma as a operator using PLY python
我有以下令牌等等,但我想保持我的問題簡短,這就是為什么不包括整個代碼。
tokens = (
'COMMA',
'OP',
'FUNC1',
'FUNC2'
)
def t_OP(t):
r'&|-|\||,'
return t
def t_FUNC1(t):
r'FUNC1'
return t
def t_FUNC2(t):
r'FUNC2'
return t
其他方法:
def FUNC1(param):
return {'a','b','c','d'}
def FUNC2(param,expression_result):
return {'a','b','c','d'}
我在 YACC 中的語法規則還有一些,但列出了重要的規則:
'expression : expression OP expression'
'expression : LPAREN expression RPAREN'
'expression : FUNC1 LPAREN PARAM RPAREN'
'expression : FUNC2 LPAREN PARAM COMMA expression RPAREN'
'expression : SET_ITEM'
在我的 yacc.py 中,以下是與問題相關的方法:
def p_expr_op_expr(p):
'expression : expression OP expression'
if p[2] == '|' or p[2]== ',':
p[0] = p[1] | p[3]
elif p[2] == '&':
p[0] = p[1] & p[3]
elif p[2] == '-':
p[0] = p[1] - p[3]
def p_expr_func1(p):
'expression : FUNC1 LPAREN PARAM RPAREN'
Param = p[3]
Result = ANY(Param)
p[0] = Result
def p_expr_func2(p):
'expression : FUNC2 LPAREN PARAM COMMA expression RPAREN'
Param = p[3]
expression_result = p[5]
Result = EXPAND(Param,expression_result)
p[0] = Result
def p_expr_set_item(p):
'expression : SET_ITEM'
p[0] = {p[1]}
所以,問題是:
如果我為此語法提供以下輸入表達式:
FUNC1("foo"),bar
-- 它工作正常,並將結果作為FUNC1("foo") and bar => {a,b,c,d} | {bar}
返回的 SET 的 UNION FUNC1("foo") and bar => {a,b,c,d} | {bar}
FUNC1("foo") and bar => {a,b,c,d} | {bar}
但是,如果我給出下面的輸入表達式,它會在 , 和 ) 處給出語法錯誤:我將括號定義為標記(對於那些認為可能沒有在標記中定義括號的人)
FUNC2("foo", FUNC1("foo"),bar)
根據我的說法,對於這個表達式,它匹配生產規則'expression : FUNC2 LPAREN PARAM COMMA expression RPAREN'
所以第一個逗號之后的所有內容都應該被很好地視為一個表達式,它應該匹配'expression : expression OP expression'
,並在遇到逗號作為運算符時進行聯合。
如果是這種情況,那么它也不適用於FUNC1("foo"),bar
。
我知道我可以通過從 t_OP(t) 中刪除 ',' 並添加另一個產生式規則作為'expression : expression COMMA expression'
來解決這個問題,該規則的方法如下所示:
def p_expr_comma_expr(p):
'expression : expression COMMA expression'
p[0] = p[1] | p[3]
我不願意包含這條規則,因為它會引入“4 班/減少沖突”。
我真的很想了解為什么它在一種情況下執行,為什么不執行另一種情況,以及將“,”視為運算符的方法是什么?
謝謝
簾布層具有沒有辦法知道你是否想要一個給定的,是語義COMMA
,或詞位OP
。 或者,更確切地說,它有一種方法,但它總是會選擇相同的方法: OP
。 這是因為標記函數中的模式在模式變量中的標記之前進行測試。
我假設你有t_COMMA = r','
在你沒有提供的程序部分的某個地方。 也可能您有一個令牌函數來識別COMMA
,在這種情況下,先出現的函數將獲勝。 但是無論你如何做到這一點,正則表達式的被測試的順序是固定的,所以無論是始終COMMA
或者它始終是OP
。 這在 Ply 手冊關於令牌規范的部分中有很好的解釋。
就個人而言,我建議從OP
刪除逗號並修改語法以在expression
的定義中使用COMMA
。 正如您所觀察到的,您將遇到 shift-reduce 沖突,因此您必須將其包含在您的優先級聲明中(您也已選擇從您的問題中省略)。 事實上,您似乎希望不同的運算符具有不同的優先級,因此您可能希望將不同的運算符分成不同的標記,因為優先級取決於標記。 請參閱 Ply 手冊部分關於優先聲明的解釋。
添加另一個規則,例如解決了我的問題:
expression:expression COMMA expression
添加是因為正如@rici 所說,在像FUNC2("hello",FUNC1("ghost"))
這樣的表達式中,第一個逗號總是被當作運算符。
並添加優先級刪除了 4shift/reduce 沖突。
precedence = (
('left','COMMA'),
('left','OP')
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.