lexer.go 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. /*
  2. Lexer only supports single-byte character sets like ASCII.
  3. @TODO convert to Unicode / UTF-8.
  4. */
  5. package lexer
  6. import (
  7. "fgm/waiig15/token"
  8. )
  9. type Lexer struct {
  10. input string
  11. position int // current position in input (points to current char)
  12. readPosition int // current reading position in input (after current char)
  13. ch byte // current char under examination
  14. }
  15. func New(input string) *Lexer {
  16. l := &Lexer{input: input}
  17. l.readChar()
  18. return l
  19. }
  20. // Give us the next character and advance our position in the input string.
  21. func (l *Lexer) readChar() {
  22. if l.readPosition >= len(l.input) {
  23. l.ch = 0
  24. } else {
  25. l.ch = l.input[l.readPosition]
  26. }
  27. l.position = l.readPosition
  28. l.readPosition += 1
  29. }
  30. func (l *Lexer) NextToken() token.Token {
  31. var tok token.Token
  32. switch l.ch {
  33. case '=':
  34. tok = newToken(token.ASSIGN, l.ch)
  35. case ';':
  36. tok = newToken(token.SEMICOLON, l.ch)
  37. case '(':
  38. tok = newToken(token.LPAREN, l.ch)
  39. case ')':
  40. tok = newToken(token.RPAREN, l.ch)
  41. case ',':
  42. tok = newToken(token.COMMA, l.ch)
  43. case '+':
  44. tok = newToken(token.PLUS, l.ch)
  45. case '{':
  46. tok = newToken(token.LBRACE, l.ch)
  47. case '}':
  48. tok = newToken(token.RBRACE, l.ch)
  49. case 0:
  50. tok.Literal = ""
  51. tok.Type = token.EOF
  52. }
  53. l.readChar()
  54. return tok
  55. }
  56. func newToken(tokenType token.TokenType, ch byte) token.Token {
  57. return token.Token{ Type: tokenType, Literal: string(ch) }
  58. }