Test with basic lexer

This commit is contained in:
Lewin Kelly 2023-12-29 09:40:40 +00:00
parent 78ec44937e
commit ebfa4528e0
4 changed files with 144 additions and 1 deletions

5
Script/go.mod Normal file
View File

@ -0,0 +1,5 @@
module MeltScript
go 1.21.3
require github.com/TwiN/go-color v1.4.1 // indirect

2
Script/go.sum Normal file
View File

@ -0,0 +1,2 @@
github.com/TwiN/go-color v1.4.1 h1:mqG0P/KBgHKVqmtL5ye7K0/Gr4l6hTksPgTgMk3mUzc=
github.com/TwiN/go-color v1.4.1/go.mod h1:WcPf/jtiW95WBIsEeY1Lc/b8aaWoiqQpu5cf8WFxu+s=

136
Script/main.go Normal file
View File

@ -0,0 +1,136 @@
package main
import (
"fmt"
"os"
"strings"
c "github.com/TwiN/go-color"
)
type token struct {
line int
column int
kind string
value string
}
const (
EOF = "EOF"
INDENT = "INDENT"
SPACE = "SPACE"
NEWLINE = "NEWLINE"
// Literals
IDENTIFIER = "IDENTIFIER"
NUMBER = "NUMBER"
// Operators
EQUALS = "EQUALS"
// that's all for now
)
func lex(source string) []token {
var tokens []token
last := func(n int) token {
return tokens[len(tokens)-n]
}
line := 1
column := 0
addToken := func(kind string, value string) {
tokens = append(tokens, token{line, column, kind, value})
}
for i := 0; i < len(source); i++ {
char := source[i]
column++
switch char {
case '=':
addToken(EQUALS, "=")
case '\n':
addToken(NEWLINE, "\n")
line++
column = 0
case ' ':
addToken(SPACE, " ")
case '\t':
if len(tokens) == 0 {
fmt.Println(c.InRed("error bruh"))
os.Exit(1)
}
// only if last token is a newline or an indent
if last(1).kind == NEWLINE || last(1).kind == INDENT {
addToken(INDENT, "\t")
} else {
addToken(SPACE, "\t")
}
default:
if char >= '0' && char <= '9' {
// keep going until we hit a non-number
var number string
for i < len(source) && source[i] >= '0' && source[i] <= '9' {
number += string(source[i])
column++
i++
}
i--
addToken(NUMBER, number)
} else if char >= 'a' && char <= 'z' || char >= 'A' && char <= 'Z' {
// keep going until we hit a non-letter
var identifier string
for i < len(source) && source[i] >= 'a' && source[i] <= 'z' || source[i] >= 'A' && source[i] <= 'Z' {
identifier += string(source[i])
column++
i++
}
i--
addToken(IDENTIFIER, identifier)
} else {
fmt.Println(c.InRed("error bruh"))
os.Exit(1)
}
}
}
return tokens
}
func main() {
if len(os.Args) < 2 {
fmt.Println(c.InRed("No target file specified!"))
fmt.Println(c.InBlue("Run 'melt-script help' for more information."))
os.Exit(1)
}
target := os.Args[1]
fi, err := os.Stat(target)
if err != nil {
fmt.Println(c.InRed("Target file ") + c.InUnderline(c.InPurple(target)) + c.InRed(" does not exist!"))
os.Exit(1)
}
if fi.IsDir() {
fmt.Println(c.InUnderline(c.InPurple(target)) + c.InRed(" is a directory, please choose a file to compile!"))
os.Exit(1)
}
source, err := os.ReadFile(target)
if err != nil {
fmt.Println(c.InRed("Failed to read target file ") + c.InUnderline(c.InPurple(target)) + c.InRed("!"))
os.Exit(1)
}
// replace \r\n with \n
sourceString := strings.Replace(string(source), "\r\n", "\n", -1)
tokens := lex(sourceString)
// ast := parse(tokens)
// out := generate(ast)
for _, token := range tokens {
fmt.Printf("%d:%d %s %s\n", token.line, token.column, c.InYellow(token.kind), c.InGreen(token.value))
}
fmt.Println("success")
}

View File

@ -1,6 +1,6 @@
module MercurySync
go 1.21.1
go 1.21.3
require (
github.com/TwiN/go-color v1.4.1