Tested and fixed a lot of expressions

This commit is contained in:
Sasha Koshka 2023-09-18 22:08:55 -04:00
parent 40514cfcf9
commit 701bf13a3a
5 changed files with 189 additions and 34 deletions

View File

@ -105,7 +105,7 @@ func (this *Reference) String () string {
// interface. A value cast is never a valid location expression. // interface. A value cast is never a valid location expression.
type ValueCast struct { type ValueCast struct {
Pos lexer.Position Pos lexer.Position
Type Expression `parser:" '[' 'cast' @@ "` Type Type `parser:" '[' 'cast' @@ "`
Value Expression `parser:" @@ ']' "` Value Expression `parser:" @@ ']' "`
} }
func (*ValueCast) expression(){} func (*ValueCast) expression(){}
@ -119,7 +119,7 @@ func (this *ValueCast) String () string {
// location expression. // location expression.
type BitCast struct { type BitCast struct {
Pos lexer.Position Pos lexer.Position
Type Expression `parser:" '[' 'bitcast' @@ "` Type Type `parser:" '[' 'bitcast' @@ "`
Value Expression `parser:" @@ ']' "` Value Expression `parser:" @@ ']' "`
} }
func (*BitCast) expression(){} func (*BitCast) expression(){}
@ -133,12 +133,13 @@ func (this *BitCast) String () string {
// be assigned to interfaces. An operation is never a valid location expression. // be assigned to interfaces. An operation is never a valid location expression.
type Operation struct { type Operation struct {
Pos lexer.Position Pos lexer.Position
Operator string `parser:" '[' @('+' | '++' | '-' | '--' | '*' | '/' | '%' | '!!' | '||' | '&&' | '^^' | '!' | '|' | '&' | '^' | '<<' | '>>' | '<' | '>' | '<=' | '>=' | '=') "` // FIXME super janky, need to make a custom lexer at some point
Operator Operator `parser:" '[' @('+''+' | '+' | '-''-' | '-' | '*' | '/' | '%' | '!''!' | '|''|' | '&''&' | '^''^' | '!' | '|' | '&' | '^' | '<''<' | '>''>' | '<' | '>' | '<''=' | '>''=' | '=') "`
Arguments []Expression `parser:" @@+ ']' "` Arguments []Expression `parser:" @@+ ']' "`
} }
func (*Operation) expression(){} func (*Operation) expression(){}
func (this *Operation) String () string { func (this *Operation) String () string {
out := "[" + this.Operator out := fmt.Sprint("[", this.Operator)
for _, argument := range this.Arguments { for _, argument := range this.Arguments {
out += fmt.Sprint(" ", argument) out += fmt.Sprint(" ", argument)
} }
@ -157,8 +158,9 @@ type Block struct {
func (*Block) expression(){} func (*Block) expression(){}
func (this *Block) String () string { func (this *Block) String () string {
out := "{" out := "{"
for _, step := range this.Steps { for index, step := range this.Steps {
out += fmt.Sprint(" ", step) if index > 0 { out += " " }
out += fmt.Sprint(step)
} }
return out + "}" return out + "}"
} }
@ -171,7 +173,7 @@ func (this *Block) String () string {
// struct being accessed is. // struct being accessed is.
type MemberAccess struct { type MemberAccess struct {
Pos lexer.Position Pos lexer.Position
Source Expression `parser:" @@ "` Source *Variable `parser:" @@ "`
Member string `parser:" '.' @Ident "` Member string `parser:" '.' @Ident "`
} }
func (*MemberAccess) expression(){} func (*MemberAccess) expression(){}
@ -184,8 +186,8 @@ func (this *MemberAccess) String () string {
// method access is never a valid location expression. // method access is never a valid location expression.
type MethodAccess struct { type MethodAccess struct {
Pos lexer.Position Pos lexer.Position
Source Expression `parser:" @@ "` Source *Variable `parser:" @@ "`
Member string `parser:" '::' @Ident "` Member string `parser:" ':' ':' @Ident "`
} }
func (*MethodAccess) expression(){} func (*MethodAccess) expression(){}
func (this *MethodAccess) String () string { func (this *MethodAccess) String () string {

View File

@ -1,6 +1,7 @@
package parser package parser
import "fmt" import "fmt"
import "strings"
import "github.com/alecthomas/participle/v2/lexer" import "github.com/alecthomas/participle/v2/lexer"
// Signature is a function or method signature that is used in functions, // Signature is a function or method signature that is used in functions,
@ -35,3 +36,86 @@ type Member struct {
func (this *Member) String () string { func (this *Member) String () string {
return fmt.Sprint(this.Name, ":", this.Value) return fmt.Sprint(this.Name, ":", this.Value)
} }
// Operator determines which operation to apply to a value in an operation
// expression.
type Operator int; const (
// Math
OperatorAdd Operator = iota
OperatorIncrement
OperatorSubtract
OperatorDecrement
OperatorMultiply
OperatorDivide
OperatorModulo
// Logic
OperatorLogicalNot
OperatorLogicalOr
OperatorLogicalAnd
OperatorLogicalXor
// Bit manipulation
OperatorNot
OperatorOr
OperatorAnd
OperatorXor
OperatorLeftShift
OperatorRightShift
// Comparison
OperatorLess
OperatorGreater
OperatorLessEqual
OperatorGreaterEqual
OperatorEqual
)
var operatorToString = []string {
// Math
"+",
"++",
"-",
"--",
"*",
"/",
"%",
// Logic
"!",
"|",
"&",
"^",
// Bit manipulation
"!!",
"||",
"&&",
"^^",
"<<",
">>",
// Comparison
"<",
">",
"<=",
">=",
"=",
}
var stringToOperator map[string] Operator
func init () {
stringToOperator = make(map[string] Operator)
for index, str := range operatorToString {
stringToOperator[str] = Operator(index)
}
}
func (this *Operator) Capture (str []string) error {
*this = stringToOperator[strings.Join(str, "")]
return nil
}
func (this Operator) String () string {
return operatorToString[this]
}

View File

@ -4,11 +4,13 @@ import "testing"
func TestType (test *testing.T) { func TestType (test *testing.T) {
testString (test, testString (test,
// correct
`BasicInt: Int `BasicInt: Int
Structure: (x:Int y:Int) Structure: (x:Int y:Int)
Interface: ([aMethod x:Int]:*U8 [otherMethod arg:5:Int]:*U8) Interface: ([aMethod x:Int]:*U8 [otherMethod arg:5:Int]:*U8)
Array: 16:16:16:Int`, Array: 16:16:16:Int
StructArray: 31:24:340920:(x:Int y:Int)`,
// input
` `
BasicInt: Int BasicInt: Int
Structure: ( Structure: (
@ -17,5 +19,58 @@ Structure: (
Interface: ( Interface: (
[aMethod x:Int]:*U8 [aMethod x:Int]:*U8
[otherMethod arg:5:Int]:*U8) [otherMethod arg:5:Int]:*U8)
Array: 16:16:16:Int`) Array: 16:16:16:Int
StructArray: 31:24:340920:(
x:Int
y:Int)
`)
}
func TestExpression (test *testing.T) {
testString (test,
// correct
`[int]:Int = 5
[var] = sdfdf
[memberAccess] = sdfdf.a
[methodAccess] = sdfdf::method
[declaration] = sdfdf:Int
[call] = [print 3 1]
[emptyBlock] = {}
[nestedBlock] = {342 93.34 {3948 32}}
[subscript] = [.arr 3]
[dereference] = [.ptr]
[reference] = [@val]
[valueCast] = [cast F32 someValue]
[bitCast] = [bitcast 4:U8 someValue]
[math] = {[+ 3 4 2 [/ 24 3]] [|| 3 [<< 56 4]] [++ 3] [-- 3] [- 3 1]}`,
// input
`
[int]:Int = 5
[var] = sdfdf
[memberAccess] = sdfdf.a
[methodAccess] = sdfdf::method
[declaration] = sdfdf:Int
[call] = [print 3 1]
[emptyBlock] = { }
[nestedBlock] = {
342
93.34
{
3948
32
}
}
[subscript] = [. arr 3]
[dereference] = [. ptr]
[reference] = [@ val]
[valueCast] = [cast F32 someValue]
[bitCast] = [bitcast 4:U8 someValue]
[math] = {
[+ 3 4 2 [/ 24 3]]
[|| 3 [<< 56 4]]
[++ 3]
[-- 3]
[- 3 1]
}
`)
} }

View File

@ -39,7 +39,7 @@ type Function struct {
// Syntax // Syntax
Pos lexer.Position Pos lexer.Position
Public bool `parser:" @'+'? "` Public bool `parser:" @'+'? "`
Signature `parser:" @@ "` Signature *Signature `parser:" @@ "`
Body Expression `parser:" ( '=' @@ )? "` Body Expression `parser:" ( '=' @@ )? "`
} }
func (*Function) topLevel(){} func (*Function) topLevel(){}
@ -60,7 +60,7 @@ type Method struct {
Pos lexer.Position Pos lexer.Position
Public bool `parser:" @'+'? "` Public bool `parser:" @'+'? "`
TypeName string `parser:" @Ident "` TypeName string `parser:" @Ident "`
Signature `parser:" '.' @@ "` Signature *Signature `parser:" '.' @@ "`
Body Expression `parser:" ( '=' @@ )? "` Body Expression `parser:" ( '=' @@ )? "`
} }
func (*Method) topLevel(){} func (*Method) topLevel(){}

View File

@ -4,6 +4,7 @@ import "io"
import "os" import "os"
import "fmt" import "fmt"
import "github.com/alecthomas/participle/v2" import "github.com/alecthomas/participle/v2"
import "github.com/alecthomas/participle/v2/lexer"
var parser = participle.MustBuild[Tree] ( var parser = participle.MustBuild[Tree] (
participle.Union[TopLevel] ( participle.Union[TopLevel] (
@ -21,24 +22,37 @@ var parser = participle.MustBuild[Tree] (
&LiteralFloat { }, &LiteralFloat { },
&LiteralArray { }, &LiteralArray { },
&LiteralStruct { }, &LiteralStruct { },
&Variable { }, &MemberAccess { },
&Declaration { }, &Declaration { },
&Call { }, &MethodAccess { },
&Variable { },
&Subscript { }, &Subscript { },
&Dereference { }, &Dereference { },
&Reference { }, &Reference { },
&ValueCast { }, &ValueCast { },
&BitCast { }, &BitCast { },
&Operation { }, &Operation { },
&Call { },
&Block { }, &Block { },
&MemberAccess { },
&MethodAccess { },
&IfElse { }, &IfElse { },
&Loop { }, // &Loop { },
&Break { }, // &Break { },
&Return { }, // &Return { },
&Assignment { }), // &Assignment { },
participle.UseLookahead(participle.MaxLookahead)) ),
participle.UseLookahead(participle.MaxLookahead),
// participle.Lexer(basicLexer),
)
var basicLexer = lexer.MustSimple([]lexer.SimpleRule {
{ Name: "Comment", Pattern: `\/\/.*`},
{ Name: "String", Pattern: `"(\\"|[^"])*"`},
{ Name: "Int", Pattern: `[-+]?\d+`},
{ Name: "Float", Pattern: `[-+]?(\d*\.)?\d+`},
{ Name: "Ident", Pattern: `[a-zA-Z_]\w*`},
{ Name: "Bracket", Pattern: `[[\]{}()]`},
{ Name: "whitespace", Pattern: `[ \t\n\r]+`},
})
// Tree represents a parsed abstract syntax tree. It has no constructor and its // Tree represents a parsed abstract syntax tree. It has no constructor and its
// zero value can be used safely. // zero value can be used safely.