More parsing

This commit is contained in:
MrLetsplay 2024-03-14 16:42:22 +01:00
parent 66651ed67c
commit cf0307c164
Signed by: mr
SSH Key Fingerprint: SHA256:92jBH80vpXyaZHjaIl47pjRq+Yt7XGTArqQg1V7hSqg
5 changed files with 66 additions and 38 deletions

View File

@ -1,6 +1,7 @@
import lang.stdlib; import lang.stdlib;
(u8, u8) a(u8 a, u8 b) { (u8, u8) a(u8 a, u8 b) {
bool a = true;
return a, b; return a, b;
} }

View File

@ -9,8 +9,6 @@ import (
) )
var Whitespace []rune = []rune{' ', '\t', '\r', '\n'} var Whitespace []rune = []rune{' ', '\t', '\r', '\n'}
var Separators []rune = []rune{'(', ')', '{', '}', ';', ','}
var Operators []rune = []rune{'=', '>', '<', '!', '+', '-', '*', '/', '%'}
type LexType uint32 type LexType uint32
@ -24,14 +22,20 @@ const (
type Keyword uint32 type Keyword uint32
var Keywords []string = []string{"import", "void", "return", "true", "false"}
const ( const (
Keyword_Import Keyword = iota Keyword_Import Keyword = iota
Keyword_Void Keyword_Void
Keyword_Return Keyword_Return
Keyword_True
KeyWord_False
) )
type Separator uint32 type Separator uint32
var Separators []rune = []rune{'(', ')', '{', '}', ';', ','}
const ( const (
Separator_OpenParen Separator = iota Separator_OpenParen Separator = iota
Separator_CloseParen Separator_CloseParen
@ -43,6 +47,8 @@ const (
type Operator uint32 type Operator uint32
var Operators []rune = []rune{'=', '>', '<', '!', '+', '-', '*', '/', '%'}
const ( const (
Operator_Equals Operator = iota Operator_Equals Operator = iota
Operator_Greater Operator_Greater
@ -60,6 +66,7 @@ type LiteralType uint32
const ( const (
Literal_String LiteralType = iota Literal_String LiteralType = iota
Literal_Number Literal_Number
Literal_Boolean
) )
type LexToken struct { type LexToken struct {
@ -168,7 +175,7 @@ func (l *Lexer) nextToken() (string, error) {
token := "" token := ""
for { for {
r := l.peekRune() r := l.peekRune()
if r == nil || slices.Contains(Whitespace, *r) || slices.Contains(Separators, *r) { if r == nil || slices.Contains(Whitespace, *r) || slices.Contains(Separators, *r) || slices.Contains(Operators, *r) {
break break
} }
@ -183,6 +190,7 @@ func (l *Lexer) nextToken() (string, error) {
} }
func parseNumber(raw string, numberType PrimitiveType) (any, error) { func parseNumber(raw string, numberType PrimitiveType) (any, error) {
// TODO: return compiler errors
if isSignedInt(numberType) { if isSignedInt(numberType) {
return strconv.ParseInt(raw, 10, getBits(numberType)) return strconv.ParseInt(raw, 10, getBits(numberType))
} }
@ -241,28 +249,21 @@ func (l *Lexer) parseToken(token string) (*LexToken, error) {
return &LexToken{Type: Type_Literal, Position: l.Position, Value: Literal{Type: Literal_Number, Primitive: numberType, Value: number}}, nil return &LexToken{Type: Type_Literal, Position: l.Position, Value: Literal{Type: Literal_Number, Primitive: numberType, Value: number}}, nil
} }
switch token { if len(runes) == 1 {
case "void": if idx := slices.Index(Separators, runes[0]); idx != -1 {
return &LexToken{Type: Type_Keyword, Position: l.Position, Value: Keyword_Void}, nil return &LexToken{Type: Type_Separator, Position: l.Position, Value: Separator(idx)}, nil
case "import": }
return &LexToken{Type: Type_Keyword, Position: l.Position, Value: Keyword_Import}, nil
case "return": if idx := slices.Index(Operators, runes[0]); idx != -1 {
return &LexToken{Type: Type_Keyword, Position: l.Position, Value: Keyword_Return}, nil return &LexToken{Type: Type_Operator, Position: l.Position, Value: Operator(idx)}, nil
case "(": }
return &LexToken{Type: Type_Separator, Position: l.Position, Value: Separator_OpenParen}, nil
case ")":
return &LexToken{Type: Type_Separator, Position: l.Position, Value: Separator_CloseParen}, nil
case "{":
return &LexToken{Type: Type_Separator, Position: l.Position, Value: Separator_OpenCurly}, nil
case "}":
return &LexToken{Type: Type_Separator, Position: l.Position, Value: Separator_CloseCurly}, nil
case ";":
return &LexToken{Type: Type_Separator, Position: l.Position, Value: Separator_Semicolon}, nil
case ",":
return &LexToken{Type: Type_Separator, Position: l.Position, Value: Separator_Comma}, nil
default:
return &LexToken{Type: Type_Identifier, Position: l.Position, Value: token}, nil
} }
if idx := slices.Index(Keywords, token); idx != -1 {
return &LexToken{Type: Type_Keyword, Position: l.Position, Value: Keyword(idx)}, nil
}
return &LexToken{Type: Type_Identifier, Position: l.Position, Value: token}, nil
} }
func lexer(program string) ([]LexToken, error) { func lexer(program string) ([]LexToken, error) {

View File

@ -18,6 +18,10 @@ func main() {
tokens, err := lexer(string(content)) tokens, err := lexer(string(content))
if err != nil { if err != nil {
if c, ok := err.(CompilerError); ok {
log.Fatalln(err, "\nv- here\n"+string([]rune(string(content))[c.Position:]))
}
log.Fatalln(err) log.Fatalln(err)
} }

View File

@ -80,8 +80,7 @@ type AssignmentExpression struct {
} }
type LiteralExpression struct { type LiteralExpression struct {
Type PrimitiveType Literal Literal
Value any
} }
type VariableReferenceExpression struct { type VariableReferenceExpression struct {
@ -349,6 +348,8 @@ func (p *Parser) tryUnaryExpression() (*Expression, error) {
} }
if token.Type == Type_Separator && token.Value.(Separator) == Separator_OpenParen { if token.Type == Type_Separator && token.Value.(Separator) == Separator_OpenParen {
// TODO: cast
paren, err := pCopy.tryParanthesizedExpression() paren, err := pCopy.tryParanthesizedExpression()
if err != nil { if err != nil {
*p = pCopy *p = pCopy
@ -359,8 +360,21 @@ func (p *Parser) tryUnaryExpression() (*Expression, error) {
*p = pCopy *p = pCopy
return paren, nil return paren, nil
} }
}
// TODO: cast if token.Type == Type_Literal {
pCopy.nextToken()
*p = pCopy
return &Expression{Type: Expression_Literal, Value: LiteralExpression{Literal: token.Value.(Literal)}}, nil
}
if token.Type == Type_Keyword {
keyword := token.Value.(Keyword)
if keyword == Keyword_True || keyword == KeyWord_False {
pCopy.nextToken()
*p = pCopy
return &Expression{Type: Expression_Literal, Value: LiteralExpression{Literal: Literal{Type: Literal_Boolean, Primitive: Primitive_Bool, Value: keyword == Keyword_True}}}, nil
}
} }
if token.Type == Type_Identifier { if token.Type == Type_Identifier {
@ -406,8 +420,9 @@ func (p *Parser) tryTupleExpression() (*Expression, error) {
token := pCopy.peekToken() token := pCopy.peekToken()
if token == nil || token.Type != Type_Separator || token.Value.(Separator) != Separator_Comma { if token == nil || token.Type != Type_Separator || token.Value.(Separator) != Separator_Comma {
if len(members) <= 1 { if len(members) == 1 {
return nil, nil // None/One experession -> not a tuple expression *p = pCopy
return expr, nil
} }
break break
@ -440,11 +455,6 @@ func (p *Parser) expect(try func() (*Expression, error), message string) (*Expre
func (p *Parser) tryDeclareLocalVariableStatement() (*Statement, error) { func (p *Parser) tryDeclareLocalVariableStatement() (*Statement, error) {
pCopy := p.copy() pCopy := p.copy()
token := pCopy.nextToken()
if token == nil {
return nil, nil
}
variableType, err := pCopy.tryType() variableType, err := pCopy.tryType()
if err != nil { if err != nil {
*p = pCopy *p = pCopy
@ -462,7 +472,7 @@ func (p *Parser) tryDeclareLocalVariableStatement() (*Statement, error) {
variableName := name.Value.(string) variableName := name.Value.(string)
token = pCopy.nextToken() token := pCopy.nextToken()
if token.Type == Type_Separator && token.Value.(Separator) == Separator_Semicolon { if token.Type == Type_Separator && token.Value.(Separator) == Separator_Semicolon {
return &Statement{Type: Statement_DeclareLocalVariable, Value: DeclareLocalVariableStatement{Variable: variableName, Initializer: nil}}, nil return &Statement{Type: Statement_DeclareLocalVariable, Value: DeclareLocalVariableStatement{Variable: variableName, Initializer: nil}}, nil
} }
@ -471,13 +481,13 @@ func (p *Parser) tryDeclareLocalVariableStatement() (*Statement, error) {
return nil, nil return nil, nil
} }
initializer, err := p.expect(p.tryExpression, "expected initializer expression") initializer, err := pCopy.expect(pCopy.tryExpression, "expected initializer expression")
if err != nil { if err != nil {
*p = pCopy *p = pCopy
return nil, err return nil, err
} }
_, err = p.expectSeparator(Separator_Semicolon) _, err = pCopy.expectSeparator(Separator_Semicolon)
if err != nil { if err != nil {
*p = pCopy *p = pCopy
return nil, err return nil, err
@ -528,6 +538,15 @@ func (p *Parser) expectStatement() (*Statement, error) {
return &Statement{Type: Statement_Block, Value: BlockStatement{Block: *block}}, nil return &Statement{Type: Statement_Block, Value: BlockStatement{Block: *block}}, nil
} }
stmt, err := p.tryDeclareLocalVariableStatement()
if err != nil {
return nil, err
}
if stmt != nil {
return stmt, nil
}
return nil, p.error("expected statement") return nil, p.error("expected statement")
} }

View File

@ -14,7 +14,9 @@ type Lang_U16 uint16
type Lang_U32 uint32 type Lang_U32 uint32
type Lang_U64 uint64 type Lang_U64 uint64
var NumberTypeNames = [...]string{"i8", "i16", "i32", "i64", "u8", "u16", "u32", "u64", "f32", "f64"} type Lang_Bool bool
var NumberTypeNames = [...]string{"i8", "i16", "i32", "i64", "u8", "u16", "u32", "u64", "f32", "f64", "bool"}
type PrimitiveType uint32 type PrimitiveType uint32
@ -29,6 +31,7 @@ const (
Primitive_U64 Primitive_U64
Primitive_F32 Primitive_F32
Primitive_F64 Primitive_F64
Primitive_Bool
) )
const InvalidValue = 0xEEEEEE // Magic value const InvalidValue = 0xEEEEEE // Magic value