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

View File

@ -1,6 +1,7 @@
package parser
import "fmt"
import "strings"
import "github.com/alecthomas/participle/v2/lexer"
// Signature is a function or method signature that is used in functions,
@ -35,3 +36,86 @@ type Member struct {
func (this *Member) String () string {
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) {
testString (test,
// correct
`BasicInt: Int
Structure: (x:Int y:Int)
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
Structure: (
@ -17,5 +19,58 @@ Structure: (
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)
`)
}
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
Pos lexer.Position
Public bool `parser:" @'+'? "`
Signature `parser:" @@ "`
Signature *Signature `parser:" @@ "`
Body Expression `parser:" ( '=' @@ )? "`
}
func (*Function) topLevel(){}
@ -60,7 +60,7 @@ type Method struct {
Pos lexer.Position
Public bool `parser:" @'+'? "`
TypeName string `parser:" @Ident "`
Signature `parser:" '.' @@ "`
Signature *Signature `parser:" '.' @@ "`
Body Expression `parser:" ( '=' @@ )? "`
}
func (*Method) topLevel(){}

View File

@ -4,6 +4,7 @@ import "io"
import "os"
import "fmt"
import "github.com/alecthomas/participle/v2"
import "github.com/alecthomas/participle/v2/lexer"
var parser = participle.MustBuild[Tree] (
participle.Union[TopLevel] (
@ -21,24 +22,37 @@ var parser = participle.MustBuild[Tree] (
&LiteralFloat { },
&LiteralArray { },
&LiteralStruct { },
&Variable { },
&MemberAccess { },
&Declaration { },
&Call { },
&MethodAccess { },
&Variable { },
&Subscript { },
&Dereference { },
&Reference { },
&ValueCast { },
&BitCast { },
&Operation { },
&Call { },
&Block { },
&MemberAccess { },
&MethodAccess { },
&IfElse { },
&Loop { },
&Break { },
&Return { },
&Assignment { }),
participle.UseLookahead(participle.MaxLookahead))
// &Loop { },
// &Break { },
// &Return { },
// &Assignment { },
),
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
// zero value can be used safely.