I am writing a parser C-like language and ran into a problem. Here is my parser, if you remove everything unnecessary from it that does not apply to the error:

from ply import lex, yacc tokens = ('LT', 'LPAREN', 'RPAREN', 'NAME') t_NAME = r'[A-Za-z_@][A-Za-z0-9_@]*' t_LPAREN = r'\(' t_RPAREN = r'\)' t_LT = r'<' t_ignore = ' ' precedence = ( ('left', 'LT'), ('left', 'CALL') ) def p_expression_binop(p): 'expression : expression LT expression' p[0] = (p[2], p[1], p[3]) def p_expression_call(p): 'expression : expression LPAREN RPAREN %prec CALL' p[0] = ('Call', p[1]) def p_expression_name(p): 'expression : NAME' p[0] = ('Name', p[1]) lexer = lex.lex() parser = yacc.yacc() print(parser.parse('a < b()')) 

If you run this example, you can get something like (spaces and indents are added for readability):

 [ ('Call', ('<', ('Name', 'a'), ('Name', 'b') ) ) ] 

As you can see, the comparison operation for some reason turned out to be more priority than the function call operation, as a result we try to compare variable (a) and function (b), and then call the result of the comparison, which is incorrect. I would like to first get a function call, and then later compare its result and variable.

At the same time, I kind of obviously set the priority (compared to <, as stated in the documentation http://www.dabeaz.com/ply/ply.html#ply_nn27 (there, however, an example with the priority of multiplication over addition, that in the full version of my grammar also works fine).

PLY does not display any warnings about conflicts in the grammar.

What is my mistake and how to fix it?

    1 answer 1

    There is no error and you do not need to receive the function call first, because it will be against the syntax tree traversal logic. Let's break the line:

     a < b() [root] |- < |- a |- b() --> вызов 

    that is, it is recognized and displayed correctly. Hence, it is impossible to reach b() without passing < . Therefore, the parser recognizes first a (or does not recognize and falls), then b() . And only the interpreter can receive the function call (although it can be embedded, as shown in the example with the calculator).

    Therefore, an error in desire, not in the code.

    • In the question tree for: (a < b)() , and it is necessary that it be: (a) < (b()) . The correct conclusion is: ('<', ('Name', 'a'), ('Call', ('Name', 'b'))) - jfs