mighty

The mighty programming language, compiler and tools (WIP)
Log | Files | Refs

commit b12b357e5400e077c52bd848f66fd8c0bf7c33d8
parent 0a4448ba4e654bc388fbb558e89afc07e9185167
Author: citbl <citbl@citbl.org>
Date:   Sun, 17 May 2026 21:07:00 +1000

future work

Diffstat:
Mmtc/lexer/lexer.go | 101++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Rmtc/parser/parser.go.old -> mtc/p.go.old | 0
Mmtc/parser/parser.go | 181+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
3 files changed, 268 insertions(+), 14 deletions(-)

diff --git a/mtc/lexer/lexer.go b/mtc/lexer/lexer.go @@ -8,6 +8,28 @@ type Kind int const ( Ident Kind = iota + + KeywordNs + KeywordIn + KeywordFrom + KeywordUse + KeywordFfi + KeywordDrop + KeywordAs + KeywordOf + KeywordAnd + KeywordOr + KeywordRef + KeywordStruct + KeywordEnum + KeywordPre + KeywordPost + KeywordInv + KeywordIf + KeywordElse + KeywordWhere + KeywordPub + Dot Colon ColonColon @@ -24,6 +46,10 @@ const ( MinusMinus LParen RParen + LBrace + RBrace + LBracket + RBracket Plus PlusEq PlusPlus @@ -32,6 +58,51 @@ const ( BadToken ) +var kindsKeywords = map[Kind]string{ + KeywordNs: "ns", + KeywordIn: "in", + KeywordFrom: "from", + KeywordUse: "use", + KeywordFfi: "ffi", + KeywordDrop: "drop", + KeywordAs: "as", + KeywordOf: "of", + KeywordAnd: "and", + KeywordOr: "or", + KeywordRef: "ref", + KeywordStruct: "struct", + KeywordEnum: "enum", + KeywordPre: "pre", + KeywordPost: "post", + KeywordInv: "inv", + KeywordIf: "if", + KeywordElse: "else", + KeywordWhere: "where", + KeywordPub: "pub", +} +var keywordKinds = map[string]Kind{ + "ns": KeywordNs, + "in": KeywordIn, + "from": KeywordFrom, + "use": KeywordUse, + "ffi": KeywordFfi, + "drop": KeywordDrop, + "as": KeywordAs, + "of": KeywordOf, + "and": KeywordAnd, + "or": KeywordOr, + "ref": KeywordRef, + "struct": KeywordStruct, + "enum": KeywordEnum, + "pre": KeywordPre, + "post": KeywordPost, + "inv": KeywordInv, + "if": KeywordIf, + "else": KeywordElse, + "where": KeywordWhere, + "pub": KeywordPub, +} + type Token struct { Kind Kind Value string @@ -67,7 +138,13 @@ func Lex(filename string, src string) []Token { i++ col++ } - res = append(res, Token{Ident, src[start:i], line, startCol}) + + ident := src[start:i] + kind := Ident + if kw, ok := keywordKinds[ident]; ok { + kind = kw + } + res = append(res, Token{kind, src[start:i], line, startCol}) continue } if is_digit(c) { @@ -145,6 +222,14 @@ func Lex(filename string, src string) []Token { res = append(res, Token{LParen, src[i : i+1], line, col}) case ')': res = append(res, Token{RParen, src[i : i+1], line, col}) + case '[': + res = append(res, Token{LBracket, src[i : i+1], line, col}) + case ']': + res = append(res, Token{RBracket, src[i : i+1], line, col}) + case '{': + res = append(res, Token{LBrace, src[i : i+1], line, col}) + case '}': + res = append(res, Token{RBrace, src[i : i+1], line, col}) default: res = append(res, Token{BadToken, src[i : i+1], line, col}) } @@ -164,6 +249,11 @@ func is_dot(c byte) bool { return c == '.' } func is_space(c byte) bool { return c == ' ' || c == '\t' || c == '\r' || c == '\n' } func (k Kind) String() string { + + if text, ok := kindsKeywords[k]; ok { + return text + } + switch k { case Dot: return "Dot" @@ -197,6 +287,14 @@ func (k Kind) String() string { return "LParen" case RParen: return "RParen" + case LBrace: + return "LBrace" + case RBrace: + return "RBrace" + case LBracket: + return "LBracket" + case RBracket: + return "RBracket" case EOF: return "EOF" case LiteralInt: @@ -217,6 +315,7 @@ func (k Kind) String() string { } func Print_tokens(tokens []Token) { + for _, tok := range tokens { fmt.Printf("%-d:%-2d %-16s %-16q\n", tok.Line, tok.Col, tok.Kind, tok.Value) } diff --git a/mtc/parser/parser.go.old b/mtc/p.go.old diff --git a/mtc/parser/parser.go b/mtc/parser/parser.go @@ -1,28 +1,189 @@ package parser -import "mighty/lexer" +import ( + "fmt" + "mighty/lexer" +) -type Node struct { - kind NodeKind - Next *Node +type Pos struct { Filename string Line, Col int } +type Node interface { + anode() + Pos() Pos +} + +func (FuncDeclNode) anode() {} + +type FuncDeclNode struct { +} + +type Program struct { +} + +func (Program) anode() {} + +type P struct { + tokens []lexer.Token + filename string + pos int + errs []error +} + +type Parameter struct { + Type AnyType + Ident lexer.Token +} + +type AnyType interface{ typeRef() } + +func (*PointerType) typeRef() {} +func (*ArrayType) typeRef() {} +func (*FuncType) typeRef() {} +func (*NamedType) typeRef() {} + +type PointerType struct{ Inner AnyType } +type ArrayType struct{ Element AnyType } + +type FuncType struct { + Params []AnyType + Return AnyType +} + +type NamedType struct { + Name lexer.Token + Type AnyType +} + func Parse(filename string, tokens []lexer.Token) Node { + return Program{} if len(tokens) < 1 { return Node{Filename: filename} } + + p := P{filename: filename, tokens: tokens} + p.parse_root() + // make program - program := Node{Filename: filename} + program := Program{} return program } +func (p *P) parse_root() { + // namespace, use, decl + for p.pos < len(p.tokens) { + //t := p.advance() + // todo namespace, use + p.parse_declaration() + } +} + +func (p *P) parse_declaration() { + //t := p.peek() + // TODO @next check for keyword being pub + if p.match(lexer.KeywordPub) { + // public declaration + p.advance() // consume pub + switch p.peek().Kind { + case lexer.KeywordStruct: + fmt.Println("struct parsing todo") + case lexer.KeywordEnum: + fmt.Println("enum parsing todo") + case lexer.Ident: + // function parsing + t_type := p.advance() + t_label := p.expect(lexer.Ident, "expected Ident for label of function decl") + p.expect(lexer.LParen, "expected a ( after function decl label") + if !p.check(lexer.RParen) { + params := parse_param_list() + } + default: + fmt.Println("undefined parsing") + } + } +} + +func (p *P) parse_param_list() []Node { + var nodes []Node + is_array := false + for p.pos < len(p.tokens) { + switch p.peek().Kind { + case lexer.LBracket: + p.advance() + p.expect(lexer.RBracket, "expect ] in type definition starting with [") + is_array = true + fallthrough + case lexer.Ident: + param_type := p.expect(lexer.Ident, "expected type of param") + param_name := p.expect(lexer.Ident, "expected name of param") + var t AnyType + if is_array { + t = &ArrayType{} + } else { + t = &NamedType{} + } + + node := Parameter{ + Ident: param_name, + Type: &NamedType{Name: param_type, Type: t}, + } + nodes = append(nodes, node) + if !p.match(lexer.Comma) { + break + } + } + return nodes + } +} + +func (p *P) peek() lexer.Token { + + if p.pos >= len(p.tokens) { + return p.tokens[len(p.tokens)-1] + } + + return p.tokens[p.pos] +} + +func (p *P) advance() lexer.Token { + tok := p.peek() + if p.pos < len(p.tokens) { + p.pos++ + } + return tok +} + +func (p *P) check(kind lexer.Kind) bool { + return p.peek().Kind == kind +} + +func (p *P) match(kind lexer.Kind) bool { + if !p.check(kind) { + return false + } + p.advance() + return true +} + +func (p *P) expect(kind lexer.Kind, msg string) lexer.Token { + if p.check(kind) { + return p.advance() + } + + p.err(p.peek(), msg) + return lexer.Token{Kind: kind} +} + +func (p *P) err(tok lexer.Token, msg string) { + p.errs = append(p.errs, fmt.Errorf("%d:%d %s", tok.Line, tok.Col, msg)) +} + type NodeKind int const ( - Program NodeKind = iota - FuncDecl + FuncDecl NodeKind = iota MethodDecl StructDecl Param @@ -57,9 +218,3 @@ const ( Equality Inequality ) - -func make_program_node(filename string) Node { - return Node{ - Filename: filename, - } -}