Вы можете указать функции регулярных выражений в Alex.
Вот, например, регулярное выражение в Alex для совпадения чисел с плавающей запятой:
$space = [\ \t\xa0]
$digit = 0-9
$octit = 0-7
$hexit = [$digit A-F a-f]
@sign = [\-\+]
@decimal = $digit+
@octal = $octit+
@hexadecimal = $hexit+
@exponent = [eE] [\-\+]? @decimal
@number = @decimal
| @decimal \. @decimal @exponent?
| @decimal @exponent
| 0[oO] @octal
| 0[xX] @hexadecimal
lex :-
@sign? @number { strtod }
Когда мы сопоставляем число с плавающей запятой, мы отправляем функцию синтаксического анализа, чтобы работать с этой захваченной строкой, которую мы можем затем обернуть и представить пользователю как функцию синтаксического анализа:
readDouble :: ByteString -> Maybe (Double, ByteString)
readDouble str = case alexScan (AlexInput '\n' str) 0 of
AlexEOF -> Nothing
AlexError _ -> Nothing
AlexToken (AlexInput _ rest) n _ ->
case strtod (B.unsafeTake n str) of d -> d `seq` Just $! (d , rest)
Хорошим следствием использования Alex для сопоставления регулярных выражений является то, что производительность хорошая, так как механизм регулярных выражений компилируется статически. Он также может быть представлен как обычная библиотека на Haskell, созданная с помощью Cabal. Для полной реализации см. bytestring-lexing .
Общий совет о том, когда использовать лексер вместо сопоставителя регулярных выражений, заключается в том, что если у вас есть грамматика для лексем, которые вы пытаетесь сопоставить, как я делал для плавающей запятой, используйте Alex. Если вы этого не сделаете, а структура является более специальной, используйте механизм регулярных выражений.