Parsec覚書
Parsecを使えば簡単にパーサかけるし余裕余裕、
と思ってたら結局手間取ってしまったので、ポイントだけ抑えておきます。
- サボらずにLexerからのParserという流れで作る
- Lexerの出力であるトークンには位置情報を仕込んで生成する
位置情報は字句解析の後の構文解析でも使う情報なので捨ててはなりません。
こんな感じなんですかね?
type Token = (SourcePos,Tok) data Tok = IdentifierToken String -- "Hoge"など | WhitespaceToken -- 空白 | LeftParenthesisToken -- '(' | RightParenthesisToken -- ')' | LeftBracketToken -- '{' | RightBracketToken -- '}' | EqualToken -- '=' | DoubleCoronToken -- '::' deriving (Show, Eq) lexemeToken :: Parser Token lexemeToken = do a <- try( many1 space ) p <- getPosition return (p,WhitespaceToken) <|> do a <- try( char '(' ) p <- getPosition return (p,LeftParenthesisToken) <|> do a <- try( char ')' ) p <- getPosition return (p,RightParenthesisToken) <|> do a <- try( char '{' ) p <- getPosition return (p,LeftBracketToken) <|> do a <- try( char '{' ) p <- getPosition return (p,RightBracketToken) <|> do a <- try( string "::" ) p <- getPosition return (p,DoubleCoronToken) <|> do a <- try( char '=' ) p <- getPosition return (p,EqualToken) <|> do a <- many1 alphaNum p <- getPosition return $ (p,IdentifierToken a) lexeme :: String -> Either ParseError [Token] lexeme cs = parse (many lexemeToken) "lexer" cs
getPositionが、もう少し何とかならんのか、という気もするのですが…
単に各do構文の外に出すだけだとは思うんですが。
ともかく、これで[Token]が手に入ります。
ここからWhitespaceTokenを消して、ようやく構文解析です。