椿の日記

たぶんプログラムの話をします

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を消して、ようやく構文解析です。