簡體   English   中英

使用 PLY python 將逗號解析為運算符時的歧義

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM