diff --git a/backend_wat.go b/backend_wat.go index 8d88293..291a5c5 100644 --- a/backend_wat.go +++ b/backend_wat.go @@ -358,7 +358,6 @@ func (c *Compiler) compileStatementWAT(stmt Statement, block *Block) (string, er return "", err } - // TODO: upcast to return type for non-primitive types return wat + "return\n", nil case Statement_DeclareLocalVariable: dlv := stmt.Value.(DeclareLocalVariableStatement) diff --git a/lexer.go b/lexer.go index e2b1778..5b43fc4 100644 --- a/lexer.go +++ b/lexer.go @@ -38,7 +38,7 @@ const ( type Separator uint32 -var Separators []rune = []rune{'(', ')', '{', '}', '[', ']', ';', ',', '.'} +var Separators []string = []string{"(", ")", "{", "}", "[", "]", ";", ",", "."} const ( Separator_OpenParen Separator = iota @@ -145,6 +145,42 @@ func (l *Lexer) tryOperator() Operator { return foundOp } +func (l *Lexer) trySeparator() Separator { + var foundSep Separator = InvalidValue + var foundSepLen int = 0 + + str := string(l.Runes) + for i, separator := range Separators { + separatorLen := len([]rune(separator)) + if separatorLen <= foundSepLen { + continue + } + + if strings.HasPrefix(str, separator) { + foundSep = Separator(i) + foundSepLen = len([]rune(separator)) + } + } + + for i := 0; i < foundSepLen; i++ { + l.nextRune() + } + + return foundSep +} + +func (l *Lexer) hasNext(choices ...string) bool { + str := string(l.Runes) + + for _, c := range choices { + if strings.HasPrefix(str, c) { + return true + } + } + + return false +} + func (l *Lexer) nextRune() *rune { if len(l.Runes) == 0 { return nil @@ -227,10 +263,15 @@ func (l *Lexer) nextToken() (*LexToken, error) { return &LexToken{Type: Type_Operator, Position: TokenPosition{SourceFile: l.SourceFile, Position: l.LastTokenPosition}, Value: op}, nil } + sep := l.trySeparator() + if sep != InvalidValue { + return &LexToken{Type: Type_Separator, Position: TokenPosition{SourceFile: l.SourceFile, Position: l.LastTokenPosition}, Value: sep}, nil + } + token := "" for { r := l.peekRune() - if r == nil || slices.Contains(Whitespace, *r) || slices.Contains(Separators, *r) { + if r == nil || slices.Contains(Whitespace, *r) || l.hasNext(Separators...) || l.hasNext(Operators...) { break } @@ -278,12 +319,6 @@ func (l *Lexer) nextToken() (*LexToken, error) { return &LexToken{Type: Type_Literal, Position: TokenPosition{SourceFile: l.SourceFile, Position: l.LastTokenPosition}, Value: Literal{Type: Literal_Number, Primitive: numberType, Value: number}}, nil } - if len(runes) == 1 { - if idx := slices.Index(Separators, runes[0]); idx != -1 { - return &LexToken{Type: Type_Separator, Position: TokenPosition{SourceFile: l.SourceFile, Position: l.LastTokenPosition}, Value: Separator(idx)}, nil - } - } - if idx := slices.Index(Keywords, token); idx != -1 { return &LexToken{Type: Type_Keyword, Position: TokenPosition{SourceFile: l.SourceFile, Position: l.LastTokenPosition}, Value: Keyword(idx)}, nil } diff --git a/parser.go b/parser.go index 1f2c346..172f0cb 100644 --- a/parser.go +++ b/parser.go @@ -166,7 +166,7 @@ type Local struct { } type Block struct { - Parent *Block // TODO: implement + Parent *Block Statements []Statement Locals map[string]Local }