lexer.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. package lexer
  2. import "github/runnignwater/monkey/token"
  3. /**
  4. * @Author: simon
  5. * @Author: ynwdlxm@163.com
  6. * @Date: 2022/10/2 上午11:07
  7. * @Desc: ASCII 码
  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. func (l *Lexer) readChar() {
  21. if l.readPosition >= len(l.input) {
  22. l.ch = 0
  23. } else {
  24. l.ch = l.input[l.readPosition]
  25. }
  26. l.position = l.readPosition
  27. l.readPosition += 1
  28. }
  29. /**
  30. * Only peek ahead in the input
  31. * and not move around in it
  32. */
  33. func (l *Lexer) peekChar() byte {
  34. if l.readPosition >= len(l.input) {
  35. return 0
  36. } else {
  37. return l.input[l.readPosition]
  38. }
  39. }
  40. func (l *Lexer) readIdentifier() string {
  41. position := l.position
  42. for isLetter(l.ch) {
  43. l.readChar()
  44. }
  45. return l.input[position:l.position]
  46. }
  47. func (l *Lexer) readNumber() string {
  48. position := l.position
  49. for isDigit(l.ch) {
  50. l.readChar()
  51. }
  52. return l.input[position:l.position]
  53. }
  54. func (l *Lexer) NextToken() token.Token {
  55. var tok token.Token
  56. l.skipWhitespace()
  57. switch l.ch {
  58. case '=':
  59. if l.peekChar() == '=' {
  60. ch := l.ch
  61. l.readChar()
  62. tok = token.Token{Type: token.EQ, Literal: string(ch) + string(l.ch)}
  63. } else {
  64. tok = newToken(token.ASSIGN, l.ch)
  65. }
  66. case ';':
  67. tok = newToken(token.SEMICOLON, l.ch)
  68. case '(':
  69. tok = newToken(token.LPAREN, l.ch)
  70. case ')':
  71. tok = newToken(token.RPAREN, l.ch)
  72. case ',':
  73. tok = newToken(token.COMMA, l.ch)
  74. case '+':
  75. tok = newToken(token.PLUS, l.ch)
  76. case '-':
  77. tok = newToken(token.MINUS, l.ch)
  78. case '!':
  79. if l.peekChar() == '=' {
  80. ch := l.ch
  81. l.readChar()
  82. tok = token.Token{Type: token.NOT_EQ, Literal: string(ch) + string(l.ch)}
  83. } else {
  84. tok = newToken(token.BANG, l.ch)
  85. }
  86. case '*':
  87. tok = newToken(token.ASTERISK, l.ch)
  88. case '/':
  89. tok = newToken(token.SLASH, l.ch)
  90. case '<':
  91. tok = newToken(token.LT, l.ch)
  92. case '>':
  93. tok = newToken(token.GT, l.ch)
  94. case '{':
  95. tok = newToken(token.LBRACE, l.ch)
  96. case '}':
  97. tok = newToken(token.RBRACE, l.ch)
  98. case 0:
  99. tok.Type = token.EOF
  100. tok.Literal = ""
  101. default:
  102. if isLetter(l.ch) {
  103. tok.Literal = l.readIdentifier()
  104. tok.Type = token.LookupIdent(tok.Literal)
  105. } else if isDigit(l.ch) {
  106. tok.Type = token.INT
  107. tok.Literal = l.readNumber()
  108. } else {
  109. tok = newToken(token.ILLEGAL, l.ch)
  110. }
  111. return tok
  112. }
  113. l.readChar()
  114. return tok
  115. }
  116. func (l *Lexer) skipWhitespace() {
  117. for l.ch == ' ' || l.ch == '\t' || l.ch == '\n' || l.ch == '\r' {
  118. l.readChar()
  119. }
  120. }
  121. func isDigit(ch byte) bool {
  122. return '0' <= ch && ch <= '9'
  123. }
  124. func isLetter(ch byte) bool {
  125. return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_'
  126. }
  127. func newToken(tokenType token.TypeToken, ch byte) token.Token {
  128. return token.Token{Type: tokenType, Literal: string(ch)}
  129. }