Мой код приводит к ошибке разбора из-за моего использования охранников - PullRequest
3 голосов
/ 10 октября 2019

У меня есть следующий код:

parseExpr :: [String] -> (Ast,[String])
parseExpr [] = error "Incorrect"
parseExpr (s:ss) | all isDigit s = (Tall (read s),ss)
              | s == "-" = let (e,ss') = parseExpr ss in (Min e,ss')
              | s == "+" = (Sum e e',ss'') where
                           (e,ss') = parseExpr ss
                           (e',ss'') = parseExpr ss'
              | s == "*" = (Mult e e',ss'') where
                           (e,ss') = parseExpr ss
                           (e',ss'') = parseExpr ss'

Когда я пытаюсь запустить его, я получаю сообщение об ошибке "parse error on input '|'. Это строка, о которой идет речь:

...
                           (e',ss'') = parseExpr ss'
->            | s == "*" = (Mult e e',ss'') where
                           (e,ss') = parseExpr ss
...

Думаю, я понимаю, почему. Я думаю, это потому, что у меня есть две линии выше, которые не экранированы охранниками, и этот хаскель запутывается, когда внезапно появляется другой охранник внизу. Но как я могу тогда добавитьдополнительные охранники после этих случаев?

Я пытался использовать точки с запятой для разделения новых строк, но я очень плохо знаком с Haskell и поэтому не очень разбираюсь в его синтаксисе.

1 Ответ

2 голосов
/ 10 октября 2019

Нет необходимости использовать фигурные скобки (хотя, конечно, вы могли бы) . Но вы должны быть осторожны с отступами. Это не так сложно, как может показаться на первый взгляд.

При этом верно, что вы не можете использовать where внутри охраняемого выражения. Вы должны использовать let в таком случае, например так:

parseExpr :: [String] -> (Ast,[String])
parseExpr [] = error "Incorrect"
parseExpr (s:ss) | all isDigit s = (Tall (read s),ss)
              | s == "-" = let (e,ss') = parseExpr ss in (Min e,ss')
              | s == "+" = let (e,ss') = parseExpr ss
                               (e',ss'') = parseExpr ss'
                           in (Sum e e',ss'')
              | s == "*" = let (e,ss') = parseExpr ss
                               (e',ss'') = parseExpr ss'
                           in (Mult e e',ss'')

Однако в вашем случае защитные выражения настолько просты, что их можно заменить на совпадения с образцом. (И желательно использовать эту возможность. Сопоставление с образцом - ваш лучший друг в Haskell.) В этом случае вы используете where.

parseExpr :: [String] -> (Ast,[String])
parseExpr [] = error "Incorrect"
parseExpr (s:ss) | all isDigit s = (Tall (read s),ss)
parseExpr ("-":ss) = (Min e,ss') where (e,ss') = parseExpr ss
parseExpr ("+":ss) = (Sum  e e',ss'') where (e, ss' ) = parseExpr ss
                                            (e',ss'') = parseExpr ss'

parseExpr ("*":ss) = (Mult e e',ss'') where (e, ss' ) = parseExpr ss
                                            (e',ss'') = parseExpr ss'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...