Haskell 解析查询(秒差距)

Haskell parsing queries (Parsec)

我正在尝试在 Haskell 中创建一个查询解析器,但不明白我应该如何允许解析器逻辑的不同可选路径。我的尝试:

query :: Parser Query
query = do
    -- add more queries
    reserved "SELECT"
    select <- sequenceOfExpr
    reserved "FROM"
    table <- identifier
    semi
    return $ Select select table (BoolConst True)
    <|> do
    reserved "SELECT"
    select <- sequenceOfExpr
    reserved "FROM"
    table <- identifier
    reserved "WHERE"
    whereQ <- bExpression
    semi
    return $ Select select table whereQ
    <|> do
    reserved "INSERT"
    insert <- sequenceOfExpr
    reserved "INTO"
    table <- identifier
    semi
    return $ Insert insert table
    <|> do
    reserved "REMOVE"
    reserved "FROM"
    table <- identifier
    reserved "WHERE"
    whereQ <- bExpression
    semi
    return $ Remove table whereQ
    <|> do
    reserved "CREATE"
    table <- identifier
    fields <- sequenceOfExpr
    semi
    return $ Create table fields
    <|> do
    reserved "DROP"
    table <- identifier
    semi
    return $ Drop table

解析对应于第一个 do stmt 结构的字符串时有效,例如:

"SELECT testField FROM testTable;"

但不适合其他人。例如。解析时:

"SELECT testField FROM testTable WHERE TRUE"

与其尝试其他路径,不如 returns:

unexpected "W"
expecting ";"

也就是说好像只试了第一种逻辑。我究竟做错了什么?

如有任何帮助,我们将不胜感激!

发生这种情况是因为 SELECT FROM 替代方案成功并返回了结果,解析从未尝试过 SELECT FROM WHERE 替代方案。

在这种情况下,我会翻转他们的顺序:先尝试 SELECT FROM WHERE,如果不起作用,再回到 SELECT FROM。您还需要将其包装在 try 中,以便解析器回滚到查询的开头。

或者,您可以使 WHERE 解析成为 SELECT FROM 解析器的条件部分,如下所示:

do
    reserved "SELECT"
    select <- sequenceOfExpr
    reserved "FROM"
    table <- identifier
    whereQ <- try (reserved "WHERE" *> bExpression) <|> (pure $ BoolConst True)
    semi
    return $ Select select table whereQ