feat: add lexer
This commit is contained in:
parent
8129c36220
commit
40cafa53f0
12
Dockerfile
Normal file
12
Dockerfile
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
ARG GO_VERSION=1.21.1
|
||||||
|
|
||||||
|
FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION}-alpine AS base
|
||||||
|
WORKDIR /src
|
||||||
|
# RUN --mount=type=bind,target=go.mod \
|
||||||
|
# --mount=type=bind,target=go.sum \
|
||||||
|
# go mod download
|
||||||
|
|
||||||
|
FROM base as tests
|
||||||
|
WORKDIR /src
|
||||||
|
RUN --mount=type=bind,target=. \
|
||||||
|
go test ./...
|
15
compose.yaml
Normal file
15
compose.yaml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
version: "3"
|
||||||
|
|
||||||
|
services:
|
||||||
|
base:
|
||||||
|
build:
|
||||||
|
target: base
|
||||||
|
volumes:
|
||||||
|
- .:/src
|
||||||
|
working_dir: /src
|
||||||
|
|
||||||
|
format:
|
||||||
|
extends:
|
||||||
|
service: base
|
||||||
|
entrypoint: "gofmt -w *.go"
|
60
lexer/lexer.go
Normal file
60
lexer/lexer.go
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package lexer
|
||||||
|
|
||||||
|
import "git.cybercyst.me/monkeylang/token"
|
||||||
|
|
||||||
|
type Lexer struct {
|
||||||
|
input string
|
||||||
|
position int
|
||||||
|
readPosition int
|
||||||
|
ch byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(input string) *Lexer {
|
||||||
|
l := &Lexer{input: input}
|
||||||
|
l.readChar()
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Lexer) readChar() {
|
||||||
|
if l.readPosition >= len(l.input) {
|
||||||
|
l.ch = 0
|
||||||
|
} else {
|
||||||
|
l.ch = l.input[l.readPosition]
|
||||||
|
}
|
||||||
|
|
||||||
|
l.position = l.readPosition
|
||||||
|
l.readPosition += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Lexer) NextToken() token.Token {
|
||||||
|
var tok token.Token
|
||||||
|
|
||||||
|
switch l.ch {
|
||||||
|
case '=':
|
||||||
|
tok = newToken(token.ASSIGN, l.ch)
|
||||||
|
case ';':
|
||||||
|
tok = newToken(token.SEMICOLON, 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 '}':
|
||||||
|
tok = newToken(token.RBRACE, l.ch)
|
||||||
|
case 0:
|
||||||
|
tok.Literal = ""
|
||||||
|
tok.Type = token.EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
l.readChar()
|
||||||
|
return tok
|
||||||
|
}
|
||||||
|
|
||||||
|
func newToken(tokenType token.TokenType, ch byte) token.Token {
|
||||||
|
return token.Token{Type: tokenType, Literal: string(ch)}
|
||||||
|
}
|
40
lexer/lexer_test.go
Normal file
40
lexer/lexer_test.go
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package lexer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.cybercyst.me/monkeylang/token"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TextNextToken(t *testing.T) {
|
||||||
|
input := `=+(){},;`
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
expectedType token.TokenType
|
||||||
|
expectedLiteral string
|
||||||
|
}{
|
||||||
|
{token.ASSIGN, "="},
|
||||||
|
{token.PLUS, "+"},
|
||||||
|
{token.LPAREN, "("},
|
||||||
|
{token.RPAREN, ")"},
|
||||||
|
{token.LBRACE, "{"},
|
||||||
|
{token.RBRACE, "}"},
|
||||||
|
{token.COMMA, ","},
|
||||||
|
{token.SEMICOLON, ";"},
|
||||||
|
}
|
||||||
|
|
||||||
|
l := New(input)
|
||||||
|
|
||||||
|
for i, tt := range tests {
|
||||||
|
tok := l.NextToken()
|
||||||
|
if tok.Type != tt.expectedType {
|
||||||
|
t.Fatalf("tests[%d] - tokentype wrong. expected=%q, got=%q",
|
||||||
|
i, tt.expectedType, tok.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tok.Literal != tt.expectedLiteral {
|
||||||
|
t.Fatalf("tests[%d] - literal wrong. expected=%q, got=%q",
|
||||||
|
i, tt.expectedLiteral, tok.Literal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
main.go
Normal file
7
main.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("Hello, World!")
|
||||||
|
}
|
31
token/token.go
Normal file
31
token/token.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package token
|
||||||
|
|
||||||
|
type TokenType string
|
||||||
|
|
||||||
|
type Token struct {
|
||||||
|
Type TokenType
|
||||||
|
Literal string
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
ILLEGAL = "ILLEGAL"
|
||||||
|
EOF = "EOF" // Identifiers + literals
|
||||||
|
IDENT = "IDENT" // add, foobar, x, y, ...
|
||||||
|
INT = "INT" // 1343456
|
||||||
|
|
||||||
|
// Operators
|
||||||
|
ASSIGN = "="
|
||||||
|
PLUS = "+"
|
||||||
|
|
||||||
|
// Delimiters
|
||||||
|
COMMA = ","
|
||||||
|
SEMICOLON = ";"
|
||||||
|
LPAREN = "("
|
||||||
|
RPAREN = ")"
|
||||||
|
LBRACE = "{"
|
||||||
|
RBRACE = "}"
|
||||||
|
|
||||||
|
// Keywords
|
||||||
|
FUNCTION = "FUNCTION"
|
||||||
|
LET = "LET"
|
||||||
|
)
|
Loading…
x
Reference in New Issue
Block a user