Ваш текущий синтаксический анализатор выражений выглядит следующим образом: BNF:
expr = funcOp ;
funcOp = attrOp , { "(" , expr, ")" } ;
attrOp = attrOp , "." , indexOp | indexOp ;
indexOp = term , { "[", expr, "]" } ;
Когда он завершит синтаксический анализ funcCall
, он не будет go выполнять резервное копирование в таблице операторов и анализировать любые attrRef
или indexRef
.
Проблема с уменьшением приоритета opAttrRef
заключается в том, что анализирует левую и правую части точки по отдельности, когда кажется, что вы хотите, чтобы парсер читал слева направо и может смешивать любой из funcCall
, attrRef
или indexRef
. Поэтому, если вы хотите иметь возможность анализировать что-то вроде a[b](c).d(e)[f]
, я бы предложил изменить opAttrRef
с инфикса на постфикс и сгладить таблицу операторов в:
exprTable = [[Postfix opIndexRef, PostFix opAttrRef, Postfix opFuncCall]]
На этом этапе анализатор становится:
expr = term , { indexRef | attrRef | funcCall } ;
Если вам нужно разрешить несколько операторов постфикса, вы можете переписать свой синтаксический анализатор выражений следующим образом:
p = liftM2 (foldl (flip ($))) pTerm (many (opAttrRef <|> opIndexRef <|> opFuncCall))
Анализатор p
можно использовать в качестве анализатора терминов. для makeExprParser
, если вы хотите добавить арифметику c, logi c и другие общие операторы.