Parse array types, Fix compiler errors
This commit is contained in:
parent
aef95b74cc
commit
99372dbc6a
53
lexer.go
53
lexer.go
@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"slices"
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -35,13 +36,15 @@ const (
|
|||||||
|
|
||||||
type Separator uint32
|
type Separator uint32
|
||||||
|
|
||||||
var Separators []rune = []rune{'(', ')', '{', '}', ';', ','}
|
var Separators []rune = []rune{'(', ')', '{', '}', '[', ']', ';', ','}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Separator_OpenParen Separator = iota
|
Separator_OpenParen Separator = iota
|
||||||
Separator_CloseParen
|
Separator_CloseParen
|
||||||
Separator_OpenCurly
|
Separator_OpenCurly
|
||||||
Separator_CloseCurly
|
Separator_CloseCurly
|
||||||
|
Separator_OpenSquare
|
||||||
|
Separator_CloseSquare
|
||||||
Separator_Semicolon
|
Separator_Semicolon
|
||||||
Separator_Comma
|
Separator_Comma
|
||||||
)
|
)
|
||||||
@ -260,7 +263,7 @@ func (l *Lexer) nextToken() (*LexToken, error) {
|
|||||||
return nil, l.error("dot in non floating-point constant")
|
return nil, l.error("dot in non floating-point constant")
|
||||||
}
|
}
|
||||||
|
|
||||||
number, err := parseNumber(rawNumber, numberType)
|
number, err := l.parseNumber(rawNumber, numberType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -281,21 +284,55 @@ func (l *Lexer) nextToken() (*LexToken, error) {
|
|||||||
return &LexToken{Type: Type_Identifier, Position: l.LastTokenPosition, Value: token}, nil
|
return &LexToken{Type: Type_Identifier, Position: l.LastTokenPosition, Value: token}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseNumber(raw string, numberType PrimitiveType) (any, error) {
|
func (l *Lexer) parseNumber(raw string, numberType PrimitiveType) (any, error) {
|
||||||
// TODO: return compiler errors
|
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) {
|
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) {
|
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) {
|
if isFloatingPoint(numberType) {
|
||||||
return strconv.ParseFloat(raw, getBits(numberType))
|
if base != 10 {
|
||||||
|
return nil, l.error("non base 10 float literals are not supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
panic("Unhandled type (" + strconv.FormatUint(uint64(numberType), 10) + ") in parseNumber()")
|
num, err := strconv.ParseFloat(raw, getBits(numberType))
|
||||||
|
if err != nil {
|
||||||
|
return nil, l.error("failed to parse literal: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return num, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
panic(fmt.Sprintf("Unhandled type %s in parseNumber()", numberType))
|
||||||
}
|
}
|
||||||
|
|
||||||
func lexer(program string) ([]LexToken, error) {
|
func lexer(program string) ([]LexToken, error) {
|
||||||
|
39
parser.go
39
parser.go
@ -221,10 +221,10 @@ func (p *Parser) trySeparator(separators ...Separator) (*Separator, error) {
|
|||||||
return &sep, nil
|
return &sep, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) expectSeparator(separators ...Separator) (Separator, error) {
|
func (p *Parser) expectSeparator(separators ...Separator) (*Separator, error) {
|
||||||
sep, err := p.trySeparator(separators...)
|
sep, err := p.trySeparator(separators...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return InvalidValue, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if sep == nil {
|
if sep == nil {
|
||||||
@ -233,10 +233,10 @@ func (p *Parser) expectSeparator(separators ...Separator) (Separator, error) {
|
|||||||
separatorNames = append(separatorNames, string(Separators[sep]))
|
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) {
|
func (p *Parser) tryOperator(operators ...Operator) (*Operator, error) {
|
||||||
@ -293,14 +293,35 @@ func (p *Parser) tryType() (*Type, error) {
|
|||||||
if tok.Type == Type_Identifier {
|
if tok.Type == Type_Identifier {
|
||||||
// TODO: array type
|
// TODO: array type
|
||||||
|
|
||||||
|
var theType Type
|
||||||
|
|
||||||
index := slices.Index(PRIMITIVE_TYPE_NAMES, tok.Value.(string))
|
index := slices.Index(PRIMITIVE_TYPE_NAMES, tok.Value.(string))
|
||||||
if index != -1 {
|
if index != -1 {
|
||||||
*p = pCopy
|
theType = Type{Type: Type_Primitive, Value: PrimitiveType(index), Position: tok.Position}
|
||||||
return &Type{Type: Type_Primitive, Value: PrimitiveType(index), Position: tok.Position}, nil
|
} 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
|
*p = pCopy
|
||||||
return &Type{Type: Type_Named, Value: tok.Value, Position: tok.Position}, nil
|
return &theType, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -339,13 +360,13 @@ func (p *Parser) expectTypeOrTupleType() (*Type, error) {
|
|||||||
|
|
||||||
types = append(types, *parsedType)
|
types = append(types, *parsedType)
|
||||||
|
|
||||||
var sep Separator
|
var sep *Separator
|
||||||
sep, err = p.expectSeparator(Separator_Comma, Separator_CloseParen)
|
sep, err = p.expectSeparator(Separator_Comma, Separator_CloseParen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if sep == Separator_CloseParen {
|
if *sep == Separator_CloseParen {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -337,7 +337,7 @@ func (v *Validator) validateStatement(stmt *Statement, functionLocals *[]Local)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !isTypeExpandableTo(*ret.Value.ValueType, *v.currentFunction.ReturnType) {
|
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 {
|
} else if v.currentFunction.ReturnType != nil {
|
||||||
errors = append(errors, v.createError("missing return value", stmt.Position))
|
errors = append(errors, v.createError("missing return value", stmt.Position))
|
||||||
|
Loading…
Reference in New Issue
Block a user