github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/lang/expressions/validate.go (about)

     1  package expressions
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/lmorg/murex/lang/expressions/symbols"
     7  )
     8  
     9  func (tree *ParserT) validateExpression(exec bool) error {
    10  	// compile data types and check for errors in the AST
    11  	//
    12  	// first walk to ensure we have a:
    13  	// value, expression, value, expression, value....etc
    14  
    15  	if tree.charPos < 0 {
    16  		tree.charPos = 0
    17  	}
    18  
    19  	if len(tree.ast) == 0 {
    20  		return fmt.Errorf("missing expression: '%s'", string(tree.expression[:tree.charPos]))
    21  	}
    22  
    23  	if len(tree.ast) == 1 &&
    24  		(tree.ast[0].key == symbols.Bareword || tree.ast[0].key == symbols.SubExpressionBegin ||
    25  			tree.ast[0].key == symbols.QuoteSingle || tree.ast[0].key == symbols.QuoteDouble) {
    26  		if tree.charPos+1 > len(tree.expression) {
    27  			tree.charPos--
    28  		}
    29  		return fmt.Errorf("not an expression: '%s'", string(tree.expression[:tree.charPos+1]))
    30  	}
    31  
    32  	var expectValue bool
    33  
    34  	for tree.astPos = 0; tree.astPos < len(tree.ast); tree.astPos++ {
    35  		prev := tree.prevSymbol()
    36  		node := tree.ast[tree.astPos]
    37  		next := tree.nextSymbol()
    38  
    39  		expectValue = !expectValue
    40  
    41  		// check for errors raised by the parser
    42  		if node.key < symbols.DataValues {
    43  			return raiseError(tree.expression, node, 0, errMessage[node.key])
    44  		}
    45  
    46  		// check each operation has a left side and right side data value
    47  		if expectValue {
    48  			if (node.key < symbols.DataValues) ||
    49  				node.key > symbols.Operations {
    50  				return raiseError(tree.expression, node, 0, "expecting a data value")
    51  			}
    52  
    53  			if node.dt != nil {
    54  				continue
    55  			}
    56  			primitive, err := node2primitive(node)
    57  			if err != nil {
    58  				return err
    59  			}
    60  			node.dt = primitive
    61  
    62  		} else {
    63  			if node.key < symbols.Operations {
    64  				return raiseError(tree.expression, node, 0, "expecting an operation")
    65  			}
    66  
    67  			switch node.key {
    68  			case symbols.Add, symbols.GreaterThan, symbols.LessThan:
    69  				if prev == nil || prev.key == symbols.Bareword ||
    70  					next == nil || next.key == symbols.Bareword {
    71  					return raiseError(tree.expression, node, 0, fmt.Sprintf("cannot %s barewords", node.key))
    72  				}
    73  
    74  			case symbols.Subtract, symbols.Divide, symbols.Multiply:
    75  				if prev == nil || (prev.key != symbols.Number && prev.key != symbols.Calculated && prev.key != symbols.SubExpressionBegin && prev.key != symbols.Scalar) ||
    76  					next == nil || (next.key != symbols.Number && next.key != symbols.Calculated && next.key != symbols.SubExpressionBegin && next.key != symbols.Scalar) {
    77  					return raiseError(tree.expression, node, 0, fmt.Sprintf("cannot %s non-numeric data types", node.key))
    78  				}
    79  			}
    80  		}
    81  
    82  	}
    83  
    84  	if !expectValue {
    85  		return raiseError(tree.expression, tree.ast[len(tree.ast)-1], 0, "unexpected end of expression")
    86  	}
    87  
    88  	return nil
    89  }