More parsing
This commit is contained in:
parent
66651ed67c
commit
cf0307c164
@ -1,6 +1,7 @@
|
||||
import lang.stdlib;
|
||||
|
||||
(u8, u8) a(u8 a, u8 b) {
|
||||
bool a = true;
|
||||
return a, b;
|
||||
}
|
||||
|
||||
|
49
lexer.go
49
lexer.go
@ -9,8 +9,6 @@ import (
|
||||
)
|
||||
|
||||
var Whitespace []rune = []rune{' ', '\t', '\r', '\n'}
|
||||
var Separators []rune = []rune{'(', ')', '{', '}', ';', ','}
|
||||
var Operators []rune = []rune{'=', '>', '<', '!', '+', '-', '*', '/', '%'}
|
||||
|
||||
type LexType uint32
|
||||
|
||||
@ -24,14 +22,20 @@ const (
|
||||
|
||||
type Keyword uint32
|
||||
|
||||
var Keywords []string = []string{"import", "void", "return", "true", "false"}
|
||||
|
||||
const (
|
||||
Keyword_Import Keyword = iota
|
||||
Keyword_Void
|
||||
Keyword_Return
|
||||
Keyword_True
|
||||
KeyWord_False
|
||||
)
|
||||
|
||||
type Separator uint32
|
||||
|
||||
var Separators []rune = []rune{'(', ')', '{', '}', ';', ','}
|
||||
|
||||
const (
|
||||
Separator_OpenParen Separator = iota
|
||||
Separator_CloseParen
|
||||
@ -43,6 +47,8 @@ const (
|
||||
|
||||
type Operator uint32
|
||||
|
||||
var Operators []rune = []rune{'=', '>', '<', '!', '+', '-', '*', '/', '%'}
|
||||
|
||||
const (
|
||||
Operator_Equals Operator = iota
|
||||
Operator_Greater
|
||||
@ -60,6 +66,7 @@ type LiteralType uint32
|
||||
const (
|
||||
Literal_String LiteralType = iota
|
||||
Literal_Number
|
||||
Literal_Boolean
|
||||
)
|
||||
|
||||
type LexToken struct {
|
||||
@ -168,7 +175,7 @@ func (l *Lexer) nextToken() (string, error) {
|
||||
token := ""
|
||||
for {
|
||||
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
|
||||
}
|
||||
|
||||
@ -183,6 +190,7 @@ func (l *Lexer) nextToken() (string, error) {
|
||||
}
|
||||
|
||||
func parseNumber(raw string, numberType PrimitiveType) (any, error) {
|
||||
// TODO: return compiler errors
|
||||
if isSignedInt(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
|
||||
}
|
||||
|
||||
switch token {
|
||||
case "void":
|
||||
return &LexToken{Type: Type_Keyword, Position: l.Position, Value: Keyword_Void}, nil
|
||||
case "import":
|
||||
return &LexToken{Type: Type_Keyword, Position: l.Position, Value: Keyword_Import}, nil
|
||||
case "return":
|
||||
return &LexToken{Type: Type_Keyword, Position: l.Position, Value: Keyword_Return}, 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 len(runes) == 1 {
|
||||
if idx := slices.Index(Separators, runes[0]); idx != -1 {
|
||||
return &LexToken{Type: Type_Separator, Position: l.Position, Value: Separator(idx)}, nil
|
||||
}
|
||||
|
||||
if idx := slices.Index(Operators, runes[0]); idx != -1 {
|
||||
return &LexToken{Type: Type_Operator, Position: l.Position, Value: Operator(idx)}, 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) {
|
||||
|
4
main.go
4
main.go
@ -18,6 +18,10 @@ func main() {
|
||||
|
||||
tokens, err := lexer(string(content))
|
||||
if err != nil {
|
||||
if c, ok := err.(CompilerError); ok {
|
||||
log.Fatalln(err, "\nv- here\n"+string([]rune(string(content))[c.Position:]))
|
||||
}
|
||||
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
|
45
parser.go
45
parser.go
@ -80,8 +80,7 @@ type AssignmentExpression struct {
|
||||
}
|
||||
|
||||
type LiteralExpression struct {
|
||||
Type PrimitiveType
|
||||
Value any
|
||||
Literal Literal
|
||||
}
|
||||
|
||||
type VariableReferenceExpression struct {
|
||||
@ -349,6 +348,8 @@ func (p *Parser) tryUnaryExpression() (*Expression, error) {
|
||||
}
|
||||
|
||||
if token.Type == Type_Separator && token.Value.(Separator) == Separator_OpenParen {
|
||||
// TODO: cast
|
||||
|
||||
paren, err := pCopy.tryParanthesizedExpression()
|
||||
if err != nil {
|
||||
*p = pCopy
|
||||
@ -359,8 +360,21 @@ func (p *Parser) tryUnaryExpression() (*Expression, error) {
|
||||
*p = pCopy
|
||||
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 {
|
||||
@ -406,8 +420,9 @@ func (p *Parser) tryTupleExpression() (*Expression, error) {
|
||||
|
||||
token := pCopy.peekToken()
|
||||
if token == nil || token.Type != Type_Separator || token.Value.(Separator) != Separator_Comma {
|
||||
if len(members) <= 1 {
|
||||
return nil, nil // None/One experession -> not a tuple expression
|
||||
if len(members) == 1 {
|
||||
*p = pCopy
|
||||
return expr, nil
|
||||
}
|
||||
|
||||
break
|
||||
@ -440,11 +455,6 @@ func (p *Parser) expect(try func() (*Expression, error), message string) (*Expre
|
||||
func (p *Parser) tryDeclareLocalVariableStatement() (*Statement, error) {
|
||||
pCopy := p.copy()
|
||||
|
||||
token := pCopy.nextToken()
|
||||
if token == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
variableType, err := pCopy.tryType()
|
||||
if err != nil {
|
||||
*p = pCopy
|
||||
@ -462,7 +472,7 @@ func (p *Parser) tryDeclareLocalVariableStatement() (*Statement, error) {
|
||||
|
||||
variableName := name.Value.(string)
|
||||
|
||||
token = pCopy.nextToken()
|
||||
token := pCopy.nextToken()
|
||||
if token.Type == Type_Separator && token.Value.(Separator) == Separator_Semicolon {
|
||||
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
|
||||
}
|
||||
|
||||
initializer, err := p.expect(p.tryExpression, "expected initializer expression")
|
||||
initializer, err := pCopy.expect(pCopy.tryExpression, "expected initializer expression")
|
||||
if err != nil {
|
||||
*p = pCopy
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = p.expectSeparator(Separator_Semicolon)
|
||||
_, err = pCopy.expectSeparator(Separator_Semicolon)
|
||||
if err != nil {
|
||||
*p = pCopy
|
||||
return nil, err
|
||||
@ -528,6 +538,15 @@ func (p *Parser) expectStatement() (*Statement, error) {
|
||||
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")
|
||||
}
|
||||
|
||||
|
5
types.go
5
types.go
@ -14,7 +14,9 @@ type Lang_U16 uint16
|
||||
type Lang_U32 uint32
|
||||
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
|
||||
|
||||
@ -29,6 +31,7 @@ const (
|
||||
Primitive_U64
|
||||
Primitive_F32
|
||||
Primitive_F64
|
||||
Primitive_Bool
|
||||
)
|
||||
|
||||
const InvalidValue = 0xEEEEEE // Magic value
|
||||
|
Loading…
Reference in New Issue
Block a user