#haskell
#haskell
Вопрос:
Я пишу анализатор для языка, предоставляемого EBNF. Все шло гладко, я успешно проанализировал «if», «then», «else», «Let», «in» и инфикс, подобный 1 2. Но когда я использую тот же подход для «», возвращается «Ничего», и я просто не знаю почему. EBNF описывает лямбду следующим образом:
block ::= cond | lambda | let | infix
lambda ::= "" var "->" block
var is a letter followed by 0 or more letters. I tested my var parser, it works
Тест настроен следующим образом:
newtype Parser a = PsrOf (String -> Maybe (String, a))
runParser :: Parser a -> String -> Maybe a
runParser (PsrOf p) inp = case p inp of
Nothing -> Nothing
Just (_, a) -> Just a
parse = runParser mainParser
testHandout =
"handout" ~: parse inp
~?= (Just (Lambda "y" (Num 3)))
Это предоставленный тип данных Expr:
data Expr
= Num Integer
| Var String
| Prim2 Op2 Expr Expr -- Prim2 op operand operand
| Let [(String, Expr)] Expr -- Let [(name, rhs), ...] body
| Lambda String Expr -- Lambda var body
| App Expr Expr -- App func arg
| Cond Expr Expr Expr -- Cond test then-branch else-branch
deriving (Eq, Show)
data Op2 = Eq | Lt | Plus | Minus | Mul | Div | Mod
deriving (Eq, Show)
Моя задача — написать mainParser. Приведенный ниже код — это часть, связанная с этим вопросом (весь код компилируется без ошибок или предупреждений)
mainParser :: Parser Expr
mainParser = whitespaces *> block <* eof
where
block = cond <|> lambda <|> letin <|> infixx <|> return (Var "Error")
lambda = do
char '\' *> whitespaces
va <- var
keyword "->"
blk <- block
return (Lambda va blk)
...more code unrelated to question
для строки
char '\' *> whitespaces
Я пытался
operator "\"
и
keyword "\"
и
string "\" *> whitespaces
ни одно из них не сработало, я ничего не получаю в результате каждый раз.
К вашему сведению, моя данная библиотека синтаксического анализа связана с этим вопросом:
char :: Char -> Parser Char
char wanted = satisfy (c -> c == wanted)
satisfy :: (Char -> Bool) -> Parser Char
satisfy pred = PsrOf p
where
p (c:cs) | pred c = Just (cs, c)
p _ = Nothing
string :: String -> Parser String
string wanted = PsrOf p
where
p inp = case stripPrefix wanted inp of
Nothing -> Nothing
Just suffix -> Just (suffix, wanted)
keyword :: String -> Parser String
keyword wanted = do
c <- satisfy isAlpha
cs <- many (satisfy isAlphaNum)
whitespaces
if c:cs == wanted then return wanted else empty
-- | Read something that looks like an operator, then skip trailing spaces.
anyOperator = some (satisfy symChar) <* whitespaces
where
symChar c = c `elem` "=/<>amp;| -*%\"
-- | Read the wanted operator, then skip trailing spaces.
operator wanted = do
sym <- anyOperator
if sym == wanted then return wanted else empty
Мой тестовый пример:
"\y->3"
Ожидаемый результат:
(Just (Lambda "y" (Num 3)))
Фактический результат:
Nothing
Я знаю, что это проблема с «», потому что я переключил «if» в моем рабочем анализаторе if then else на «» then else, и анализатор if then else мгновенно сломался.
Также я хочу хотя бы попытаться получить сообщение об ошибке, поэтому я добавил
lambda = (do ...... ) <|> return (Var "lambdaError")
в конце лямбда-блока в mainParser, но вместо Just (Var «lambdaError») Я все еще ничего не получаю.
Как разобрать »? Или, по крайней мере, как проверить, в чем здесь проблема?
Комментарии:
1. Попробуйте ввести
lambda
сначалаblock
, так что что-то вродеblock = lambda <|> cond <|> ...
. (Я не уверен, что это сработает, но иногда такие вещи работают хорошо.)2. Нет, это не так. Но я думаю, что я мог бы понять, в чем проблема. «->» также неправильно анализируется
3. Может ли кто-нибудь задать этот вопрос решаемым?
Ответ №1:
NVM я обнаружил проблему
operator "\"
на самом деле работает, но
keyword "->"
не потому, что ключевое слово анализирует только буквы, вот почему я ничего не получал при использовании operator «». Поэтому я собираюсь использовать оператор «» и написать синтаксический анализатор только для «->»
В конце концов это сработало:
lambda = do
operator "\"
va <- var
char '-'
operator ">"
blk <- block
return (Lambda va blk)
Комментарии:
1. Когда я это делаю, я получаю это: > Вы можете принять свой собственный ответ через 2 дня
2. Почему бы и нет
operator “->”
?