commit 308881ef7bfcfa3943a70e24f1a1e5e0a005e1d9
parent 3292841b13ea847c0c384e5709e9e6ad340694f7
Author: keyle <keyle@capsule.org>
Date: Sat, 16 May 2026 16:39:58 +1000
lexer wip
Diffstat:
6 files changed, 224 insertions(+), 0 deletions(-)
diff --git a/mtc/go.mod b/mtc/go.mod
@@ -0,0 +1,3 @@
+module mighty
+
+go 1.26.2
diff --git a/mtc/lexer/lexer.go b/mtc/lexer/lexer.go
@@ -0,0 +1,185 @@
+package lexer
+
+import "fmt"
+
+type Kind int
+
+const (
+ Ident Kind = iota
+ Plus
+ PlusEq
+ PlusPlus
+ Colon
+ ColonColon
+ Minus
+ MinusEq
+ MinusMinus
+ LParen
+ RParen
+ EOF
+ IntLiteral
+ FloatLiteral
+ StringLiteral
+ CharLiteral
+ BoolLiteral
+ BadToken
+)
+
+type Token struct {
+ Kind Kind
+ Value string
+ Line, Col int
+}
+
+func Lex(src string) []Token {
+ var res []Token
+ i := 0
+ line := 1
+ col := 1
+
+ for i < len(src) {
+
+ c := src[i]
+ if is_space(c) {
+ if c == '\n' {
+ line++
+ col = 1
+ } else {
+ col++
+ }
+ i++
+ continue
+ }
+
+ start := i
+ startCol := col
+
+ if is_alpha(c) || is__(c) {
+ for i < len(src) && (is_alphanum(src[i]) || is__(src[i])) {
+ i++
+ col++
+ }
+ res = append(res, Token{Ident, src[start:i], line, startCol})
+ continue
+ }
+ if is_digit(c) {
+ numeric := IntLiteral
+ for i < len(src) && (is_digit(src[i]) || is__(src[i]) && is_dot(src[i])) {
+ if is_dot(src[i]) {
+ numeric = FloatLiteral
+ }
+ i++
+ col++
+ }
+
+ res = append(res, Token{numeric, src[start:i], line, startCol})
+ continue
+ }
+ var cx byte
+ if i+1 < len(src) {
+ cx = src[i+1]
+ }
+ switch c {
+ case ':':
+ switch cx {
+ case ':':
+ res = append(res, Token{ColonColon, src[i : i+2], line, col})
+ i++
+ col++
+ default:
+ res = append(res, Token{Colon, src[i : i+1], line, col})
+ }
+ case '+':
+ switch cx {
+ case '=':
+ res = append(res, Token{PlusEq, src[i : i+2], line, col})
+ i++
+ col++
+ case '+':
+ res = append(res, Token{PlusPlus, src[i : i+2], line, col})
+ i++
+ col++
+ default:
+ res = append(res, Token{Plus, src[i : i+1], line, col})
+ }
+ case '(':
+ res = append(res, Token{LParen, src[i : i+1], line, col})
+ case ')':
+ res = append(res, Token{RParen, src[i : i+1], line, col})
+ default:
+ res = append(res, Token{BadToken, src[i : i+1], line, col})
+ }
+
+ i++
+ col++
+ }
+ res = append(res, Token{EOF, "", line, col})
+ return res
+}
+
+func is_space(c byte) bool {
+ return c == ' ' || c == '\t' || c == '\r' || c == '\n'
+}
+
+func is_alpha(c byte) bool {
+ return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'
+}
+
+func is_alphanum(c byte) bool {
+ return is_alpha(c) || is_digit(c)
+}
+
+func is__(c byte) bool { return c == '_' }
+func is_dot(c byte) bool { return c == '.' }
+
+func is_digit(c byte) bool {
+ return c >= '0' && c <= '9'
+}
+
+func (k Kind) String() string {
+ switch k {
+ case Ident:
+ return "Ident"
+ case Plus:
+ return "Plus"
+ case PlusEq:
+ return "PlusEq"
+ case PlusPlus:
+ return "PlusPlus"
+ case Minus:
+ return "Minus"
+ case MinusEq:
+ return "MinusEq"
+ case MinusMinus:
+ return "MinusMinus"
+ case Colon:
+ return "Colon"
+ case ColonColon:
+ return "ColonColon"
+ case LParen:
+ return "LParen"
+ case RParen:
+ return "RParen"
+ case EOF:
+ return "EOF"
+ case IntLiteral:
+ return "IntLiteral"
+ case FloatLiteral:
+ return "FloatLiteral"
+ case StringLiteral:
+ return "StringLiteral"
+ case CharLiteral:
+ return "CharLiteral"
+ case BoolLiteral:
+ return "BoolLiteral"
+ case BadToken:
+ return "BAD~~~TOKEN"
+ default:
+ return "Unknown"
+ }
+}
+func Print_tokens(tokens []Token) {
+ for _, tok := range tokens {
+ fmt.Printf("%-d:%-2d %-12s %-12q\n", tok.Line, tok.Col, tok.Kind, tok.Value)
+ }
+}
diff --git a/mtc/main.go b/mtc/main.go
@@ -0,0 +1,20 @@
+package main
+
+import (
+ "fmt"
+ "os"
+
+ l "mighty/lexer"
+)
+
+func main() {
+ args := os.Args[1:]
+ fmt.Println(args[0])
+ data, err := os.ReadFile(args[0])
+ if err != nil {
+ panic(err)
+ }
+
+ tokens := l.Lex(string(data))
+ l.Print_tokens(tokens)
+}
diff --git a/mtc/makefile b/mtc/makefile
@@ -0,0 +1,2 @@
+default:
+ go run . test.mty
diff --git a/mtc/target.mty b/mtc/target.mty
@@ -0,0 +1,12 @@
+int add(int a, int b) =
+ a + b
+int main() ::
+ ret add(1, 2)
+
+// target QBE:
+
+export function w $add(w %a, w %b) {
+@start
+ %r =w add %a, %b
+ ret %r
+}
diff --git a/mtc/test.mty b/mtc/test.mty
@@ -0,0 +1,2 @@
+int main() ::
+ io.putln("hello world " + 123)