Запрос комментариев на простой Алекс парсер


Я рассматривал возможность добавления кода в Редактор Haskell Yi и хочу добавить в него режимы git commit и rebase. Я никогда ничего не делал с Алексом раньше, поэтому я решил написать автономный синтаксический анализатор коммитов за пределами Yi, прежде чем пытаться добавить его в Редактор. Я не смог найти много документации по Alex, кроме документов на странице Alex, которые являются действительно светом информации о оболочке монады, которая, похоже, является тем, что эмулирует проект Yi.

Мог бы кто-нибудь прокомментирует мне, что не так (и, надеюсь, правильно) в этом коде? Я довольно новичок в Хаскелле, поэтому любые комментарии там также будут оценены. Идея заключается в том, что это будет правильно обрабатывать строки сообщений, комментарии и строки различий (которые будут находиться под всеми вышеперечисленными при запуске git commit -v). Я могу добавить поддержку для дифференциации между строкой дайджеста и последующими строками позже, но я хотел остаться простым сейчас.


{
module Main where
}

%wrapper "monad"

$commitChars = [$printablet]
@diffStart = diff --git $commitChars*

gitCommit :-

 {
^@diffStart$                   {makeAlexAction DiffDeclaration `andBegin` diff}
^# $commitChars*$             {makeAlexAction Comment}
$commitChars*$                 {makeAlexAction MessageLine}
}

 {
^@diffStart$                   {makeAlexAction DiffDeclaration}
^- $commitChars*$             {makeAlexAction DiffRemove}
^+ $commitChars*$             {makeAlexAction DiffAdd}
^$commitChars*$                {makeAlexAction DiffContext}
}

.                                     ;
[nr]                                ;

{
data GitCommitToken = Digest String
                    | MessageLine String
                    | Comment String
                    | DiffDeclaration String
                    | DiffAdd String
                    | DiffRemove String
                    | DiffContext String
                    | CommitEOF
                  deriving (Show, Eq)

makeAlexAction ::Monad m => (String -> GitCommitToken) ->AlexInput ->Int ->m GitCommitToken
makeAlexAction cons =  (_,_,inp) len ->return $cons (take len inp)

alexEOF = return CommitEOF

alexMonadScanTokens ::Alex [GitCommitToken]
alexMonadScanTokens = do                                                                                 
  inp  alexEOF >>= eof ->return [eof]
    AlexError inp' ->alexError $ "lexical error: " ++ show inp'
    AlexSkip  inp' len ->do
        alexSetInput inp'
        alexMonadScanTokens
    AlexToken inp' len action ->do
        alexSetInput inp'
        token &lt- action inp len
        tokens &lt-alexMonadScanTokens
        return $ token : tokens

main = do
     s &lt- getContents
     mapM_ print $ either (_ -> []) id (runAlex s alexMonadScanTokens)
}
1 2

1 ответ:

Во-первых, спасибо за вклад в Haskell и Yi!

обзор кода

  • я бы использовал синтаксический анализ bytestring. Алекс поддерживает это сейчас. Используйте режим %wrapper "strict-bytestring".
  • either (\_ -> []) id: Немного странно. Я бы использовал явный случай, с лучшей ошибкой для сбоя синтаксического анализа.
  • имеет ли он утечку пространства в alexMonadScanTokens (по крайней мере, он потребляет стек). Алекс определяет alexScanTokens для вас, чтобы быть левым сгибом над входом. Я думаю, что вы должны использовать alexMonadScan
  • в тяжелом дежурный парсер, я бы использовал распакованные, строгие байтестринги для типов токенов. Например, Digest !ByteString
  • ваши регексы выглядят отлично.

Резюме, довольно хороший первый ход! Переключитесь на синтаксический анализ bytestring и попробуйте протестировать некоторые большие файлы, чтобы убедиться, что ваш сканер не имеет утечки пространства, предполагая, что вы не используете out-of-the-box alexScanTokens.

ресурсы

Посмотрите на пакетbytestring-lexing для синтаксического анализатора Alex на основе bytestring. Во-вторых, сам пакет Алекса имеет много хороших примеров, которые могут помочь с идиоматическим разбором:

  $ cabal unpack alex
  $ cd examples