-1

次のような式を解析したい: a().x. のようになりますEAttrRef (EFuncCall (EVarRef "a") []) "x"。残念ながら、式パーサーがすぐに停止してしまいます。解析しa()てから停止するだけです。

1:4:
  |
1 | a().x
  |    ^
unexpected '.'
expecting end of input

コード:

pExpr :: Parser Expr
pExpr = lexeme p & dbg "pExpr" <?> "expression"
  where
    pTerm = try pVarRef <|> pELit
    p = makeExprParser pTerm exprTable
    exprTable = [[Postfix opIndexRef], [InfixL opAttrRef], [Postfix opFuncCall]]
    opAttrRef :: Parser (Expr -> Expr -> Expr)
    opAttrRef = do
      symbol "." & dbg "opAttrRef symbol \".\""
      return r
      where
        r x (EVarRef y) = EAttrRef x y
        r x y = error [qq|opAttrRef got unexpected right operand $y (left operand was $x)|]
    opFuncCall :: Parser (Expr -> Expr)
    opFuncCall = do
      symbol "("
      args <- sepBy pExpr (symbol ",")
      symbol ")" & dbg "opFuncCall symbol \")\""
      return $ \funcExpr -> EFuncCall funcExpr args
    opIndexRef = do
      symbol "["
      e <- pExpr
      symbol "]" & dbg "opIndexRef symbol \"]\""
      return $ \obj -> EIndexRef obj e

デバッグ出力:

opAttrRef symbol "."> IN: "().x"
opAttrRef symbol "."> MATCH (EERR): <EMPTY>
opAttrRef symbol "."> ERROR:
opAttrRef symbol "."> offset=1:
opAttrRef symbol "."> unexpected '('
opAttrRef symbol "."> expecting '.'

pExpr> IN: ").x"
pExpr> MATCH (EERR): <EMPTY>
pExpr> ERROR:
pExpr> offset=2:
pExpr> unexpected ").x"
pExpr> expecting "false", "null", "true", '"', '+', '-', '[', digit, identifier, or integer

opFuncCall symbol ")"> IN: ").x"
opFuncCall symbol ")"> MATCH (COK): ')'
opFuncCall symbol ")"> VALUE: ")"

pExpr> IN: "a().x"
pExpr> MATCH (COK): "a()"
pExpr> VALUE: EFuncCall (EVarRef "a") []

(インデックスアクセスのデバッグ出力がどのように見えるかと比較して)2回目makeExprParserは呼び出されていないように思えますが、そうでない理由はわかりません。opFuncCall

優先順位を下げると解析されopAttrRefますが、間違ったツリーが生成されます (たとえば、正しいオペランドはx.a()どちらa()が間違っているか、そうである必要がaあり、全体が関数呼び出しにある必要があります)、それを使用することはできません (私はかなりその言語の参照に基づいているため、現在の優先度が正しいことを確認してください)。

4

1 に答える 1