module lexer
interface LexerState
  source: string
  current: number
  tokens: Token[]
interface Token
  type: string
  value: string
init source (LexerState, string -> LexerState) :=
  { self | source = source, current = 1, tokens = {} }
match pattern tokentype (LexerState, string, string -> LexerState, boolean) :=
  let
    position, value = self.source:match ('()(' .. pattern .. ')') self.current
  in
    if position == self.current then
      let
        token = { type = 'tokentype', value = value }
      in
        { self |
          current = self.current + 1,
          tokens = self.tokens :: token,
        }, true
    else
      self, false
lex done (LexerState, boolean? -> Token[]?, string?) :=
  if not done then
    let
      self, success = self:match '[%a_][%w_]' 'name'
        or self:match '%d*%.?%d+' 'number'
        or self:match '%=' 'equals'
        or self:match '%+' 'plus'
        or self:match '%s+'
    in
      if success then
        self:lex self.current <= #self.tokens
      else
        let
          errformat = "unexpected character '%s'"
          errmsg = errformat:format (self.source:sub self.current self.current)
        in
          nil, errmsg
  else
    self.tokens, nil
new ... (...any -> LexerState) =
  let
    self = setmetatable {} { __index = lexer }
  in
    init self ...
          Last active
          June 1, 2016 02:48 
        
      - 
      
- 
        Save itsMapleLeaf/f4ff3d265bb615ef430ba906b4f3c64d to your computer and use it in GitHub Desktop. 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment