diff options
| author | Charlie Stanton <charlie@shtanton.xyz> | 2023-04-19 13:23:47 +0100 | 
|---|---|---|
| committer | Charlie Stanton <charlie@shtanton.xyz> | 2023-04-19 13:27:38 +0100 | 
| commit | aea1a08d6a9d378137d467d3e1f1ccc40232b725 (patch) | |
| tree | 680e7c913b3ea782557d51968e24d7fa5c4d450a /subex | |
| parent | b48dcb0d37bd3db854927df25e6ff41d07501026 (diff) | |
| download | stred-go-aea1a08d6a9d378137d467d3e1f1ccc40232b725.tar | |
Adds the negate operator
Negates all of the numbers produced by its content subex
Diffstat (limited to 'subex')
| -rw-r--r-- | subex/arithmetic.go | 33 | ||||
| -rw-r--r-- | subex/parse.go | 2 | ||||
| -rw-r--r-- | subex/subexast.go | 14 | 
3 files changed, 49 insertions, 0 deletions
| diff --git a/subex/arithmetic.go b/subex/arithmetic.go index 7200ac7..5497a68 100644 --- a/subex/arithmetic.go +++ b/subex/arithmetic.go @@ -85,3 +85,36 @@ func multiplyValues(atoms []walk.Atom) ([]walk.Atom, error) {  		return []walk.Atom{walk.ValueNumber(product)}, nil  	}  } + +// Does tries to cast all to numbers and negates them +func negateValues(atoms []walk.Atom) ([]walk.Atom, error) { +	var negatedNumbers []walk.Atom +	values, err := walk.MemoryCompound(atoms) +	if err != nil { +		return nil, err +	} +	for _, value := range values { +		switch v := value.(type) { +			case walk.ValueNull: +				negatedNumbers = append(negatedNumbers, walk.ValueNumber(0)) +			case walk.ValueBool: +				if bool(v) { +					negatedNumbers = append(negatedNumbers, walk.ValueNumber(-1)) +				} else { +					negatedNumbers = append(negatedNumbers, walk.ValueNumber(0)) +				} +			case walk.ValueNumber: +				negatedNumbers = append(negatedNumbers, walk.ValueNumber(-v)) +			case walk.ValueString: +				num, err := strconv.ParseFloat(string(v), 64) +				if err == nil { +					negatedNumbers = append(negatedNumbers, walk.ValueNumber(-num)) +				} else { +					return nil, errors.New("Tried to sum non-castable string") +				} +			default: +				return nil, errors.New("Tried to sum non-number") +		} +	} +	return negatedNumbers, nil +} diff --git a/subex/parse.go b/subex/parse.go index f73d060..8635186 100644 --- a/subex/parse.go +++ b/subex/parse.go @@ -238,6 +238,8 @@ func parseSubex(l *RuneReader, minPower int) SubexAST {  				lhs = SubexASTSum {lhs}  			case r == '*' && minPower <= 8:  				lhs = SubexASTProduct {lhs} +			case r == '-' && minPower <= 8: +				lhs = SubexASTNegate {lhs}  			case r == '$' && minPower <= 8:  				slot := l.next()  				if slot == eof { diff --git a/subex/subexast.go b/subex/subexast.go index abf0ca6..3c807ee 100644 --- a/subex/subexast.go +++ b/subex/subexast.go @@ -209,3 +209,17 @@ func (ast SubexASTProduct) compileWith(next SubexState) SubexState {  		}),  	}  } + +// Runs the content Subex, if all outputted atoms can be cast to numbers, outputs them all negated +// Rejects if this fails +type SubexASTNegate struct { +	content SubexAST +} +func (ast SubexASTNegate) compileWith(next SubexState) SubexState { +	return &SubexCaptureBeginState { +		next: ast.content.compileWith(&SubexArithmeticEndState { +			next: next, +			calculate: negateValues, +		}), +	} +} | 
