From 1e9bd34a84a38dac060e33a78fa84407b04737f3 Mon Sep 17 00:00:00 2001 From: Chuck Smith Date: Sun, 14 Jan 2024 21:24:49 -0500 Subject: [PATCH] add additional keywords and evaluators to lexer --- .idea/git_toolbox_prj.xml | 15 +++++++++++ .idea/vcs.xml | 6 +++++ lexer/lexer.go | 51 +++++++++++++++++++++++++++++++---- lexer/lexer_test.go | 57 +++++++++++++++++++++++++++++++++++++++ token/token.go | 28 ++++++++++++++++--- 5 files changed, 148 insertions(+), 9 deletions(-) create mode 100644 .idea/git_toolbox_prj.xml create mode 100644 .idea/vcs.xml diff --git a/.idea/git_toolbox_prj.xml b/.idea/git_toolbox_prj.xml new file mode 100644 index 0000000..02b915b --- /dev/null +++ b/.idea/git_toolbox_prj.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/lexer/lexer.go b/lexer/lexer.go index d04bd69..30bccf8 100644 --- a/lexer/lexer.go +++ b/lexer/lexer.go @@ -25,6 +25,14 @@ func (l *Lexer) readChar() { l.readPosition += 1 } +func (l *Lexer) peekChar() byte { + if l.readPosition >= len(l.input) { + return 0 + } else { + return l.input[l.readPosition] + } +} + func (l *Lexer) NextToken() token.Token { var tok token.Token @@ -32,17 +40,50 @@ 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.PLUS, l.ch) + case '-': + tok = newToken(token.MINUS, l.ch) + case '!': + 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 '*': + tok = newToken(token.ASTERISK, l.ch) + case '<': + tok = newToken(token.LT, l.ch) + case '>': + tok = newToken(token.GT, l.ch) case ';': tok = newToken(token.SEMICOLON, l.ch) + case ',': + tok = newToken(token.COMMA, l.ch) case '(': tok = newToken(token.LPAREN, l.ch) case ')': tok = newToken(token.RPAREN, l.ch) - case ',': - tok = newToken(token.COMMA, l.ch) - case '+': - tok = newToken(token.PLUS, l.ch) case '{': tok = newToken(token.LBRACE, l.ch) case '}': diff --git a/lexer/lexer_test.go b/lexer/lexer_test.go index 42a604e..eb6e2cf 100644 --- a/lexer/lexer_test.go +++ b/lexer/lexer_test.go @@ -14,6 +14,17 @@ let add = fn(x, y) { }; let result = add(five, ten); +!-/*5; +5 < 10 > 5; + +if (5 < 10) { + return true; +} else { + return false; +} + +10 == 10; +10 != 9; ` tests := []struct { @@ -56,6 +67,52 @@ let result = add(five, ten); {token.IDENT, "ten"}, {token.RPAREN, ")"}, {token.SEMICOLON, ";"}, + + {token.BANG, "!"}, + {token.MINUS, "-"}, + {token.SLASH, "/"}, + {token.ASTERISK, "*"}, + {token.INT, "5"}, + {token.SEMICOLON, ";"}, + {token.INT, "5"}, + {token.LT, "<"}, + {token.INT, "10"}, + {token.GT, ">"}, + {token.INT, "5"}, + {token.SEMICOLON, ";"}, + + {token.IF, "if"}, + {token.LPAREN, "("}, + {token.INT, "5"}, + {token.LT, "<"}, + {token.INT, "10"}, + {token.RPAREN, ")"}, + {token.LBRACE, "{"}, + + {token.RETURN, "return"}, + {token.TRUE, "true"}, + {token.SEMICOLON, ";"}, + + {token.RBRACE, "}"}, + {token.ELSE, "else"}, + {token.LBRACE, "{"}, + + {token.RETURN, "return"}, + {token.FALSE, "false"}, + {token.SEMICOLON, ";"}, + + {token.RBRACE, "}"}, + + {token.INT, "10"}, + {token.EQ, "=="}, + {token.INT, "10"}, + {token.SEMICOLON, ";"}, + + {token.INT, "10"}, + {token.NOT_EQ, "!="}, + {token.INT, "9"}, + {token.SEMICOLON, ";"}, + {token.EOF, ""}, } diff --git a/token/token.go b/token/token.go index 76b951a..5cae921 100644 --- a/token/token.go +++ b/token/token.go @@ -16,8 +16,18 @@ const ( INT = "INT" // 123456 // Operators - ASSIGN = "=" - PLUS = "+" + ASSIGN = "=" + PLUS = "+" + MINUS = "-" + BANG = "!" + ASTERISK = "*" + SLASH = "/" + + LT = "<" + GT = ">" + + EQ = "==" + NOT_EQ = "!=" // Delimiters COMMA = "," @@ -31,11 +41,21 @@ const ( // Keywords FUNCTION = "FUNCTION" LET = "LET" + TRUE = "TRUE" + FALSE = "FALSE" + IF = "IF" + ELSE = "ELSE" + RETURN = "RETURN" ) var keywords = map[string]TokenType{ - "fn": FUNCTION, - "let": LET, + "fn": FUNCTION, + "let": LET, + "true": TRUE, + "false": FALSE, + "if": IF, + "else": ELSE, + "return": RETURN, } func LookupIdent(ident string) TokenType {