The Lexer

Our initial language has very simple lexical syntax.

integer: 1, -2, 42

  1. integer :: Parser Integer
  2. integer = Tok.integer lexer

float: 3.14, 2.71, 0.0

  1. float :: Parser Double
  2. float = Tok.float lexer

identifier: a, b, foo, ncc1701d

  1. identifier :: Parser String
  2. identifier = Tok.identifier lexer

And several tokens which enclose other token(s) returning a compose expression.

  1. parens :: Parser a -> Parser a
  2. parens = Tok.parens lexer
  3. semiSep :: Parser a -> Parser [a]
  4. semiSep = Tok.semiSep lexer
  5. commaSep :: Parser a -> Parser [a]
  6. commaSep = Tok.commaSep lexer

Lastly our lexer requires that several tokens be reserved and not used as identifiers, we reference these as separately.

reserved: def, extern

reservedOp: +, *, -, ;

  1. reserved :: String -> Parser ()
  2. reserved = Tok.reserved lexer
  1. reservedOp :: String -> Parser ()
  2. reservedOp = Tok.reservedOp lexer

Putting it all together we have our Lexer.hs module.

  1. module Lexer where
  2. import Text.Parsec.String (Parser)
  3. import Text.Parsec.Language (emptyDef)
  4. import qualified Text.Parsec.Token as Tok
  5. lexer :: Tok.TokenParser ()
  6. lexer = Tok.makeTokenParser style
  7. where
  8. ops = ["+","*","-",";"]
  9. names = ["def","extern"]
  10. style = emptyDef {
  11. Tok.commentLine = "#"
  12. , Tok.reservedOpNames = ops
  13. , Tok.reservedNames = names
  14. }
  15. integer :: Parser Integer
  16. integer = Tok.integer lexer
  17. float :: Parser Double
  18. float = Tok.float lexer
  19. parens :: Parser a -> Parser a
  20. parens = Tok.parens lexer
  21. commaSep :: Parser a -> Parser [a]
  22. commaSep = Tok.commaSep lexer
  23. semiSep :: Parser a -> Parser [a]
  24. semiSep = Tok.semiSep lexer
  25. identifier :: Parser String
  26. identifier = Tok.identifier lexer
  27. reserved :: String -> Parser ()
  28. reserved = Tok.reserved lexer
  29. reservedOp :: String -> Parser ()
  30. reservedOp = Tok.reservedOp lexer