Browse Source

§1.4 final: two-character operator tokens.

Frederic G. MARAND 5 years ago
parent
commit
16c838ac4e
3 changed files with 45 additions and 6 deletions
  1. 25 3
      lexer/lexer.go
  2. 16 1
      lexer/lexer_test.go
  3. 4 2
      token/token.go

+ 25 - 3
lexer/lexer.go

@@ -7,7 +7,7 @@ package lexer
 
 import (
 	"fgm/waiig15/token"
-	)
+)
 
 type Lexer struct {
 	input        string
@@ -40,7 +40,14 @@ func (l *Lexer) NextToken() token.Token {
 
 	switch l.ch {
 	case '=':
-		tok = newToken(token.ASSIGN, l.ch)
+		if l.peekChar() == '=' {
+			ch := l.ch
+			l.readChar()
+			literal := string(ch) + string(l.ch)
+			tok = token.Token{Type: token.EQ, Literal: literal}
+		} else {
+			tok = newToken(token.ASSIGN, l.ch)
+		}
 	case '(':
 		tok = newToken(token.LPAREN, l.ch)
 	case ')':
@@ -50,7 +57,14 @@ func (l *Lexer) NextToken() token.Token {
 	case '-':
 		tok = newToken(token.MINUS, l.ch)
 	case '!':
-		tok = newToken(token.BANG, l.ch)
+		if l.peekChar() == '=' {
+			ch := l.ch
+			l.readChar()
+			literal := string(ch) + string(l.ch)
+			tok = token.Token{Type: token.NOT_EQ, Literal: literal}
+		} else {
+			tok = newToken(token.BANG, l.ch)
+		}
 	case '/':
 		tok = newToken(token.SLASH, l.ch)
 	case '*':
@@ -94,6 +108,14 @@ func newToken(tokenType token.TokenType, ch byte) token.Token {
 	return token.Token{Type: tokenType, Literal: string(ch)}
 }
 
+func (l *Lexer) peekChar() byte {
+	if l.readPosition >= len(l.input) {
+		return 0
+	} else {
+		return l.input[l.readPosition]
+	}
+}
+
 func (l *Lexer) readIdentifier() string {
 	position := l.position
 	for isLetter(l.ch) {

+ 16 - 1
lexer/lexer_test.go

@@ -23,7 +23,11 @@ if (5 < 10) {
 }
 else {
 	return false;
-}`
+}
+
+10 == 10;
+10 != 9;
+`
 
 	tests := []struct {
 		expectedType    token.TokenType
@@ -105,6 +109,17 @@ else {
 		{token.FALSE, "false"},
 		{token.SEMICOLON, ";"},
 		{token.RBRACE, "}"},
+
+		// 64
+		{ token.INT, "10"},
+		{ token.EQ, "=="},
+		{ token.INT, "10"},
+		{ token.SEMICOLON, ";"},
+		{ token.INT, "10"},
+		{ token.NOT_EQ, "!="},
+		{ token.INT, "9"},
+		{ token.SEMICOLON, ";"},
+
 		{token.EOF, ""},
 	}
 

+ 4 - 2
token/token.go

@@ -23,8 +23,10 @@ const (
 	ASTERISK = "*"
 	SLASH    = "/"
 
-	LT = "<"
-	GT = ">"
+	LT     = "<"
+	GT     = ">"
+	EQ     = "=="
+	NOT_EQ = "!="
 
 	// Delimiters.
 	COMMA     = ","