Запросы на разбор Haskell (Parsec) - PullRequest
1 голос
/ 30 сентября 2019

Я пытаюсь сделать парсер запросов в 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"

Вместо того, чтобы пробовать другие пути, он возвращает:

unexpected "W"
expecting ";"

Другими словами, кажется, что он пробует только первую логику. Что я делаю неправильно?

Любая помощь будет высоко ценится!

1 Ответ

2 голосов
/ 30 сентября 2019

Это происходит потому, что альтернатива SELECT FROM прошла успешно и вернула свой результат, синтаксический анализ никогда не пытался попробовать альтернативу SELECT FROM WHERE.

В этом конкретном случае я бы просто перевернул их порядок: try *Сначала 1005 *, и если это не сработает, вернитесь к 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
...