lexLine :: String -> Either Error [L]
lexLine str = spaceout <$> fix [] empty str
  where
    empty = []
    emit acc ls = Token   (reverse acc) : ls
    finish = Right . reverse
    fix ls acc s | null s = finish $ emit acc ls
    fix ls acc s | isSpace (head s) = fix (emit acc ls) empty (tail s)
    fix ls acc s | '\"' == head s =
      let l' = emit acc ls in
      case reads s of
        [(str, rest)] -> fix (String str : l') empty rest
        _ -> Left $ "error parsing string: " ++ s
    fix ls acc s | '#' == head s =
      finish . (Comment (tail s) :) . (emit acc) $ ls
    fix ls acc s = fix ls (head s : acc) (tail s)

-- TODO support multiline strings?
lexLine :: String -> Either Error [L]
lexLine str = spaceout <$> fix [] empty str
  where
    empty = []
    emit acc ls = Token   (reverse acc) : ls
    finish = Right . reverse
    fix ls acc s | null s = finish $ emit acc ls
    fix ls acc s | isSpace (head s) = fix (emit acc ls) empty (tail s)
    fix ls acc s | '\"' == head s =
      let l' = emit acc ls in
      case reads s of
        [(str, rest)] -> fix (String str : l') empty rest
        _ -> Left $ "error parsing string: " ++ s
    fix ls acc s | '#' == head s =
      finish . (Comment (tail s) :) . (emit acc) $ ls
    fix ls acc s = fix ls (head s : acc) (tail s)

-- TODO support multiline strings?
lexLine str = spaceout <$> fix [] empty str
  where
    empty = []
    emit acc ls = Token   (reverse acc) : ls
    finish = Right . reverse
    fix ls acc s | null s = finish $ emit acc ls
    fix ls acc s | isSpace (head s) = fix (emit acc ls) empty (tail s)
    fix ls acc s | '\"' == head s =
      let l' = emit acc ls in
      case reads s of
        [(str, rest)] -> fix (String str : l') empty rest
        _ -> Left $ "error parsing string: " ++ s
    fix ls acc s | '#' == head s =
      finish . (Comment (tail s) :) . (emit acc) $ ls
    fix ls acc s = fix ls (head s : acc) (tail s)

-- TODO support multiline strings?