Haskell: сопоставление строковых префиксов со списком - PullRequest
0 голосов
/ 25 февраля 2019

В последнее время я изучал немного Хаскелла и подумал, что лексер может быть интересным проектом.Я использую эту грамматику ANSI C Yacc в качестве руководства.

Общая структура программы:

lex :: [Char] -> Maybe [Token]
lex s =
  case tokenize([], s) of
    Just (tokens, []) -> Just tokens
    _ -> Nothing

tokenize :: ([Token], [Char]) -> Maybe ([Token], [Char])

Где tokenize создает список токенов. У меня возникают проблемы с поиском подходящей структуры для tokenize. Например, для соответствия ключевым словам типа int, я мог бы написать:

tokenize (toks, 'i':'n':'t':' ':rest) = tokenize (toks++[TokenKeyword IntK], rest)

Но это похожеужасный способ делать вещи.Есть ли способ сопоставить шаблон с элементами в списке?Могу ли я создать список всех ключевых слов и попытаться сопоставить их как префиксы входной строки?

1 Ответ

0 голосов
/ 25 февраля 2019

Если вы хотите сопоставить на основе строкового префикса, вы можете использовать расширение ViewPatterns .Это расширение можно включить, передав в компилятор -XViewPatterns, запустив :set -XViewPatterns в ghci или поставив {-# LANGUAGE ViewPatterns #-} вверху файла.

Затем вы можете написать функцию matchPrefix(не на 100% оптимально, поскольку он повторяется по prefix дважды):

matchPrefix :: String -> String -> Maybe String
matchPrefix prefix result
  | and (zipWith (==) prefix result) = Just (drop (length prefix) result)
  | otherwise = Nothing

А затем используйте его в схеме, подобной следующей:

startsWithInt :: String -> Bool
startsWithInt (matchPrefix "int " -> Just rest) = True
startsWithInt _ = False

Если вы хотитесопоставлять на основе списка токенов и извлекать оставшуюся часть строки, а также сопоставить токен, вы можете сделать это, изменив matchPrefix, чтобы сделать это вместо этого.

...