From 99372dbc6a571943e521e2e560a2abe23ca4a35f Mon Sep 17 00:00:00 2001 From: MrLetsplay Date: Thu, 28 Mar 2024 18:20:52 +0100 Subject: [PATCH] Parse array types, Fix compiler errors --- lexer.go | 53 ++++++++++++++++++++++++++++++++++++++++++++-------- parser.go | 39 +++++++++++++++++++++++++++++--------- validator.go | 2 +- 3 files changed, 76 insertions(+), 18 deletions(-) diff --git a/lexer.go b/lexer.go index f4b3e2a..4b80dd2 100644 --- a/lexer.go +++ b/lexer.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "slices" "strconv" "strings" @@ -35,13 +36,15 @@ const ( type Separator uint32 -var Separators []rune = []rune{'(', ')', '{', '}', ';', ','} +var Separators []rune = []rune{'(', ')', '{', '}', '[', ']', ';', ','} const ( Separator_OpenParen Separator = iota Separator_CloseParen Separator_OpenCurly Separator_CloseCurly + Separator_OpenSquare + Separator_CloseSquare Separator_Semicolon Separator_Comma ) @@ -260,7 +263,7 @@ func (l *Lexer) nextToken() (*LexToken, error) { return nil, l.error("dot in non floating-point constant") } - number, err := parseNumber(rawNumber, numberType) + number, err := l.parseNumber(rawNumber, numberType) if err != nil { return nil, err } @@ -281,21 +284,55 @@ func (l *Lexer) nextToken() (*LexToken, error) { return &LexToken{Type: Type_Identifier, Position: l.LastTokenPosition, Value: token}, nil } -func parseNumber(raw string, numberType PrimitiveType) (any, error) { - // TODO: return compiler errors +func (l *Lexer) parseNumber(raw string, numberType PrimitiveType) (any, error) { + if numberType == Primitive_Bool { + return nil, l.error("bool not allowed as number suffix") + } + + base := 10 + if strings.HasPrefix(raw, "0x") { + raw = raw[2:] + base = 16 + } else if strings.HasPrefix(raw, "0o") { + raw = raw[2:] + base = 8 + } else if strings.HasPrefix(raw, "0b") { + raw = raw[2:] + base = 2 + } + if isSignedInt(numberType) { - return strconv.ParseInt(raw, 10, getBits(numberType)) + num, err := strconv.ParseInt(raw, base, getBits(numberType)) + if err != nil { + return nil, l.error("failed to parse literal: " + err.Error()) + } + + return num, nil } if isUnsignedInt(numberType) { - return strconv.ParseUint(raw, 10, getBits(numberType)) + num, err := strconv.ParseUint(raw, base, getBits(numberType)) + if err != nil { + return nil, l.error("failed to parse literal: " + err.Error()) + } + + return num, nil } if isFloatingPoint(numberType) { - return strconv.ParseFloat(raw, getBits(numberType)) + if base != 10 { + return nil, l.error("non base 10 float literals are not supported") + } + + num, err := strconv.ParseFloat(raw, getBits(numberType)) + if err != nil { + return nil, l.error("failed to parse literal: " + err.Error()) + } + + return num, nil } - panic("Unhandled type (" + strconv.FormatUint(uint64(numberType), 10) + ") in parseNumber()") + panic(fmt.Sprintf("Unhandled type %s in parseNumber()", numberType)) } func lexer(program string) ([]LexToken, error) { diff --git a/parser.go b/parser.go index 41e7c3b..a245302 100644 --- a/parser.go +++ b/parser.go @@ -221,10 +221,10 @@ func (p *Parser) trySeparator(separators ...Separator) (*Separator, error) { return &sep, nil } -func (p *Parser) expectSeparator(separators ...Separator) (Separator, error) { +func (p *Parser) expectSeparator(separators ...Separator) (*Separator, error) { sep, err := p.trySeparator(separators...) if err != nil { - return InvalidValue, err + return nil, err } if sep == nil { @@ -233,10 +233,10 @@ func (p *Parser) expectSeparator(separators ...Separator) (Separator, error) { separatorNames = append(separatorNames, string(Separators[sep])) } - return InvalidValue, p.error("expected one of " + strings.Join(separatorNames, " ")) + return nil, p.error("expected one of " + strings.Join(separatorNames, " ")) } - return *sep, nil + return sep, nil } func (p *Parser) tryOperator(operators ...Operator) (*Operator, error) { @@ -293,14 +293,35 @@ func (p *Parser) tryType() (*Type, error) { if tok.Type == Type_Identifier { // TODO: array type + var theType Type + index := slices.Index(PRIMITIVE_TYPE_NAMES, tok.Value.(string)) if index != -1 { - *p = pCopy - return &Type{Type: Type_Primitive, Value: PrimitiveType(index), Position: tok.Position}, nil + theType = Type{Type: Type_Primitive, Value: PrimitiveType(index), Position: tok.Position} + } else { + theType = Type{Type: Type_Named, Value: tok.Value, Position: tok.Position} + } + + for { + sep, err := pCopy.trySeparator(Separator_OpenSquare) + if err != nil { + return nil, err + } + + if sep == nil { + break + } + + _, err = pCopy.expectSeparator(Separator_CloseSquare) + if err != nil { + return nil, err + } + + theType = Type{Type: Type_Array, Value: ArrayType{ElementType: theType}, Position: theType.Position} } *p = pCopy - return &Type{Type: Type_Named, Value: tok.Value, Position: tok.Position}, nil + return &theType, nil } return nil, nil @@ -339,13 +360,13 @@ func (p *Parser) expectTypeOrTupleType() (*Type, error) { types = append(types, *parsedType) - var sep Separator + var sep *Separator sep, err = p.expectSeparator(Separator_Comma, Separator_CloseParen) if err != nil { return nil, err } - if sep == Separator_CloseParen { + if *sep == Separator_CloseParen { break } } diff --git a/validator.go b/validator.go index 2747b10..75873ea 100644 --- a/validator.go +++ b/validator.go @@ -337,7 +337,7 @@ func (v *Validator) validateStatement(stmt *Statement, functionLocals *[]Local) } if !isTypeExpandableTo(*ret.Value.ValueType, *v.currentFunction.ReturnType) { - errors = append(errors, v.createError("expression type does not match function return type", ret.Value.Position)) + errors = append(errors, v.createError(fmt.Sprintf("cannot return value of type %s from function returning %s", *ret.Value.ValueType, *v.currentFunction.ReturnType), ret.Value.Position)) } } else if v.currentFunction.ReturnType != nil { errors = append(errors, v.createError("missing return value", stmt.Position))