parser.go (3626B)
package parser
import (
"fmt"
"mighty/lexer"
)
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 := 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 (
FuncDecl NodeKind = iota
MethodDecl
StructDecl
Param
FieldDecl
Block
CallExpr
Return
Ident
Type
BinaryExpr
UnaryExpr
SubscriptExpr
If
Else
Use
Namespace
From
Pre
Post
Where
Result
Error
)
type OpKind int
const (
Plus = iota
Minus
Mul
Div
Equality
Inequality
)