Tested and fixed a lot of expressions
This commit is contained in:
parent
40514cfcf9
commit
701bf13a3a
@ -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 {
|
||||
|
@ -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]
|
||||
}
|
||||
|
@ -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]
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
@ -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(){}
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user