我开始学习Alex并相信我已经到了有状态上下文会有所帮助的地步,但我不完全确定如何去做。我正在尝试对erlang binaries的有限子集进行 lex 。使用以下词法分析器:
{
module Main (main, Token(..), AlexPosn(..), alexScanTokens, token_posn) where
}
%wrapper "posn"
$digit = 0-9 -- digits
$alpha = [a-zA-Z] -- alphabetic characters
$dbl_quote = \"
tokens :-
$white+ ;
"," { tok (\p s -> Comma p) }
"<<" { tok (\p s -> BinaryOpen p) }
">>" { tok (\p s -> BinaryClose p) }
$dbl_quote [^$dbl_quote]* $dbl_quote { tok (\p s -> ErlStr p (init (tail s))) }
$digit+ { tok (\p s -> ErlInt p (read s)) }
{
-- action helpers:
tok :: (AlexPosn -> String -> Token) -> AlexPosn -> String -> Token
tok f p s = f p s
data Token =
Comma AlexPosn |
BinaryOpen AlexPosn |
BinaryClose AlexPosn |
ErlInt AlexPosn Integer |
ErlStr AlexPosn String
deriving (Eq, Show)
token_posn :: Token -> AlexPosn
token_posn (Comma p) = p
token_posn (BinaryOpen p) = p
token_posn (BinaryClose p) = p
token_posn (ErlInt p _) = p
token_posn (ErlStr p _) = p
main :: IO ()
main = do
s <- getContents
print (alexScanTokens s)
}
我做得很好。例如,
> alex so_erlang_lexer.x && ghc --make -o erlexer so_erlang_lexer.hs && echo '<<"100", 1>>' | ./erlexer
[1 of 1] Compiling Main ( so_erlang_lexer.hs, so_erlang_lexer.o )
Linking erlexer ...
[BinaryOpen (AlexPn 0 1 1),ErlStr (AlexPn 2 1 3) "100",Comma (AlexPn 7 1 8),ErlInt (AlexPn 9 1 10) 1,BinaryClose (AlexPn 10 1 11)]
我希望lexed返回等效于Binary [ErlStr "100", ErlInt 1]
,但我无法找到一个使用在我脑海中点击的起始代码的词法分析器。
- 此处引用的 GHC 词法分析器不使用任何 Alex 包装器。
- Alex 自己的关于其 monad 和 monadUserState 包装器的文档让我不确定应该选择哪个以及如何使用它们。
- 亚历克斯关于老虎的例子是最有希望的,但它太大了,我很难澄清我的无知。
- 这个问题使用了 monad 解析器,但似乎没有使用它的状态特性。
有人会好心指导我吗?