More parsing
This commit is contained in:
parent
66651ed67c
commit
cf0307c164
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
49
lexer.go
49
lexer.go
@ -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":
|
|
||||||
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 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) {
|
func lexer(program string) ([]LexToken, error) {
|
||||||
|
4
main.go
4
main.go
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
45
parser.go
45
parser.go
@ -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")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
5
types.go
5
types.go
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user