From 5f2ff5e74e39aef0c5d40c50fa8bbba541da499f Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Fri, 28 Jun 2024 23:13:55 +0200 Subject: [PATCH] Added more tests --- src/build/expression/Expression.go | 8 ++--- src/build/expression/Expression_test.go | 36 +++++++++++++++++++ src/build/expression/Operator.go | 46 +++++++++++++------------ src/build/scan.go | 2 +- src/build/token/Tokenize.go | 11 +++++- 5 files changed, 73 insertions(+), 30 deletions(-) diff --git a/src/build/expression/Expression.go b/src/build/expression/Expression.go index c2be790..7776c35 100644 --- a/src/build/expression/Expression.go +++ b/src/build/expression/Expression.go @@ -109,14 +109,10 @@ func (expr *Expression) write(builder *strings.Builder) { builder.WriteByte('(') builder.WriteString(expr.Token.Text()) - builder.WriteByte(' ') - for i, child := range expr.Children { + for _, child := range expr.Children { + builder.WriteByte(' ') child.write(builder) - - if i != len(expr.Children)-1 { - builder.WriteByte(' ') - } } builder.WriteByte(')') diff --git a/src/build/expression/Expression_test.go b/src/build/expression/Expression_test.go index e267a60..eb992c6 100644 --- a/src/build/expression/Expression_test.go +++ b/src/build/expression/Expression_test.go @@ -118,6 +118,28 @@ func TestEachLeaf(t *testing.T) { assert.Equal(t, err.Error(), "error") } +func TestEachParameter(t *testing.T) { + src := []byte("1+2,3*4,5*6,7+8") + tokens := token.Tokenize(src) + parameters := []string{} + + err := expression.EachParameter(tokens, func(parameter token.List) error { + expr := expression.Parse(parameter) + parameters = append(parameters, expr.String()) + return nil + }) + + assert.Nil(t, err) + assert.DeepEqual(t, parameters, []string{"(+ 1 2)", "(* 3 4)", "(* 5 6)", "(+ 7 8)"}) + + err = expression.EachParameter(tokens, func(parameter token.List) error { + return fmt.Errorf("error") + }) + + assert.NotNil(t, err) + assert.Equal(t, err.Error(), "error") +} + func TestRemoveChild(t *testing.T) { src := []byte("(1+2-3*4)+(5*6-7+8)") tokens := token.Tokenize(src) @@ -141,3 +163,17 @@ func TestNilGroup(t *testing.T) { expr := expression.Parse(tokens) assert.Nil(t, expr) } + +func TestInvalidOperator(t *testing.T) { + src := []byte("a +++ 2") + tokens := token.Tokenize(src) + expr := expression.Parse(tokens) + assert.Equal(t, expr.String(), "(+++ a 2)") +} + +func TestInvalidOperatorCall(t *testing.T) { + src := []byte("+++()") + tokens := token.Tokenize(src) + expr := expression.Parse(tokens) + assert.NotNil(t, expr) +} diff --git a/src/build/expression/Operator.go b/src/build/expression/Operator.go index 391ed74..5e50dc5 100644 --- a/src/build/expression/Operator.go +++ b/src/build/expression/Operator.go @@ -16,27 +16,29 @@ type Operator struct { // Operators defines the operators used in the language. // The number corresponds to the operator priority and can not be zero. var Operators = map[string]*Operator{ - ".": {".", 13, 2}, - "λ": {"λ", 12, 1}, - "!": {"!", 11, 1}, - "*": {"*", 10, 2}, - "/": {"/", 10, 2}, - "%": {"%", 10, 2}, - "+": {"+", 9, 2}, - "-": {"-", 9, 2}, - ">>": {">>", 8, 2}, - "<<": {"<<", 8, 2}, - ">": {">", 7, 2}, - "<": {"<", 7, 2}, - ">=": {">=", 7, 2}, - "<=": {"<=", 7, 2}, - "==": {"==", 6, 2}, - "!=": {"!=", 6, 2}, - "&": {"&", 5, 2}, - "^": {"^", 4, 2}, - "|": {"|", 3, 2}, - "&&": {"&&", 2, 2}, - "||": {"||", 1, 2}, + ".": {".", 13, 2}, + "λ": {"λ", 12, 1}, + "!": {"!", 11, 1}, + "*": {"*", 10, 2}, + "/": {"/", 10, 2}, + "%": {"%", 10, 2}, + "+": {"+", 9, 2}, + "-": {"-", 9, 2}, + ">>": {">>", 8, 2}, + "<<": {"<<", 8, 2}, + "&": {"&", 7, 2}, + "^": {"^", 6, 2}, + "|": {"|", 5, 2}, + + ">": {">", 4, 2}, + "<": {"<", 4, 2}, + ">=": {">=", 4, 2}, + "<=": {"<=", 4, 2}, + "==": {"==", 3, 2}, + "!=": {"!=", 3, 2}, + "&&": {"&&", 2, 2}, + "||": {"||", 1, 2}, + "=": {"=", math.MinInt, 2}, ":=": {":=", math.MinInt, 2}, "+=": {"+=", math.MinInt, 2}, @@ -56,7 +58,7 @@ func isComplete(expr *Expression) bool { return true } - if expr.Token.Kind == token.Operator && len(expr.Children) >= numOperands(expr.Token.Text()) { + if expr.Token.Kind == token.Operator && len(expr.Children) == numOperands(expr.Token.Text()) { return true } diff --git a/src/build/scan.go b/src/build/scan.go index 15fdfe9..93149b7 100644 --- a/src/build/scan.go +++ b/src/build/scan.go @@ -114,7 +114,7 @@ func scanFile(path string, functions chan<- *Function) error { break } - if tokens[i].Kind == token.NewLine { + if tokens[i].Kind == token.NewLine || tokens[i].Kind == token.Comment { i++ continue } diff --git a/src/build/token/Tokenize.go b/src/build/token/Tokenize.go index b2fc798..5388b4b 100644 --- a/src/build/token/Tokenize.go +++ b/src/build/token/Tokenize.go @@ -59,15 +59,24 @@ func Tokenize(buffer []byte) List { // Comment case '/': if i+1 >= len(buffer) || buffer[i+1] != '/' { - tokens = append(tokens, Token{Operator, i, buffer[i : i+1]}) + position := i i++ + + for i < len(buffer) && isOperator(buffer[i]) { + i++ + } + + tokens = append(tokens, Token{Operator, position, buffer[position:i]}) continue } + position := i + for i < len(buffer) && buffer[i] != '\n' { i++ } + tokens = append(tokens, Token{Comment, position, buffer[position:i]}) continue // String