diff options
| -rw-r--r-- | subex/main.go | 29 | ||||
| -rw-r--r-- | subex/main_test.go | 77 | ||||
| -rw-r--r-- | subex/parse.go | 20 | ||||
| -rw-r--r-- | subex/subexstate.go | 5 | 
4 files changed, 114 insertions, 17 deletions
| diff --git a/subex/main.go b/subex/main.go index 982b585..32a5cf3 100644 --- a/subex/main.go +++ b/subex/main.go @@ -150,8 +150,7 @@ type auxiliaryState struct {  	outputStack OutputStack  	// How deeply nested the current execution is inside of the overall value  	// i.e. starts at zero, is incremented to one when entering an array -	nestingLen int -	nestingValue bool +	nesting []bool  }  func (aux auxiliaryState) cloneStore() auxiliaryState { @@ -227,8 +226,15 @@ func (pair SubexEatBranch) accepting() []OutputStack {  }  func equalStates(left SubexEatBranch, right SubexEatBranch) bool { -	// Only care about if they are the same pointer -	return left.state == right.state && left.aux.nestingLen == right.aux.nestingLen && left.aux.nestingValue == right.aux.nestingValue +	if left.state != right.state || len(left.aux.nesting) != len(right.aux.nesting) { +		return false +	} +	for i, l := range left.aux.nesting { +		if l != right.aux.nesting[i] { +			return false +		} +	} +	return true  }  // If two branches have the same state, only the first has a chance of being successful @@ -254,9 +260,6 @@ func addStates(curStates []SubexEatBranch, newStates []SubexBranch, nesting []bo  		case SubexEpsilonState:  			curStates = addStates(curStates, s.epsilon(state.aux), nesting)  		case SubexEatState: -			if state.aux.nestingLen < len(nesting) && state.aux.nestingLen > 0 { -				state.aux.nestingValue = nesting[state.aux.nestingLen - 1] -			}  			curStates = append(curStates, SubexEatBranch{  				state: s,  				aux:   state.aux, @@ -270,12 +273,13 @@ func processInput(states []SubexEatBranch, input walk.Edible, nesting []bool) []  	newStates := make([]SubexEatBranch, 0, 2)  	for _, state := range states { -		if state.aux.nestingLen > len(nesting) { +		if len(state.aux.nesting) > len(nesting) {  			continue  		} -		if (state.aux.nestingLen == len(nesting) && -				(len(nesting) == 0 || state.aux.nestingValue || nesting[len(nesting) - 1])) { +		if (len(state.aux.nesting) == len(nesting) && +				(len(state.aux.nesting) == 0 || len(nesting) == 0 || +				state.aux.nesting[len(nesting) - 1] || nesting[len(nesting) - 1])) {  			newStates = addStates(newStates, state.eat(input), nesting)  		} else {  			newStates = append(newStates, state) @@ -320,8 +324,7 @@ func RunTransducer(transducer Transducer, input []walk.Value) (output []walk.Val  				values: make([][]walk.Value, transducer.storeSize.values),  				runes:  make([][]rune, transducer.storeSize.runes),  			}, -			nestingLen: 0, -			nestingValue: true, +			nesting: nil,  		},  	}}, nil) @@ -334,7 +337,7 @@ func RunTransducer(transducer Transducer, input []walk.Value) (output []walk.Val  	}  	for _, state := range states { -		if state.aux.nestingLen > 0 { +		if len(state.aux.nesting) > 0 {  			continue  		}  		acceptingStacks := state.accepting() diff --git a/subex/main_test.go b/subex/main_test.go index 9c1819a..8e98798 100644 --- a/subex/main_test.go +++ b/subex/main_test.go @@ -79,6 +79,21 @@ func TestSubexMain(t *testing.T) {  			},  		},  		{ +			subex: `#(".".{-0})-`, +			input: []walk.Value { +				walk.MapValue { +					{ +						Key: "a", +						Value: walk.NullValue{}, +					}, +				}, +			}, +			expected: []walk.Value { +				walk.StringValue("a"), +				walk.NullValue{}, +			}, +		}, +		{  			subex: "@(..$a`$a$a`{-0})@",  			input: []walk.Value {  				walk.ArrayValue { @@ -328,6 +343,68 @@ func TestSubexMain(t *testing.T) {  				},  			},  		}, +		{ +			subex: ":(.`null`{-0})#", +			input: []walk.Value { +				walk.ArrayValue { +					{ +						Index: 0, +						Value: walk.StringValue("a"), +					}, +					{ +						Index: 1, +						Value: walk.StringValue("b"), +					}, +					{ +						Index: 2, +						Value: walk.StringValue("c"), +					}, +				}, +			}, +			expected: []walk.Value { +				walk.MapValue { +					{ +						Key: "a", +						Value: walk.NullValue{}, +					}, +					{ +						Key: "b", +						Value: walk.NullValue{}, +					}, +					{ +						Key: "c", +						Value: walk.NullValue{}, +					}, +				}, +			}, +		}, +		{ +			subex: `#(".$_(.{-0})".{-0})#`, +			input: []walk.Value { +				walk.MapValue { +					{ +						Key: "hello", +						Value: walk.NullValue{}, +					}, +					{ +						Key: "world", +						Value: walk.NullValue{}, +					}, +				}, +			}, +			expected: []walk.Value { +				walk.MapValue { +					{ +						Key: "ello", +						Value: walk.NullValue{}, +					}, +					{ +						Key: "orld", +						Value: walk.NullValue{}, +					}, +				}, +			}, +		},  	}  	for i, test := range tests { diff --git a/subex/parse.go b/subex/parse.go index 1e17bb3..d7fe243 100644 --- a/subex/parse.go +++ b/subex/parse.go @@ -413,11 +413,29 @@ func parseSubex(l RuneReader, minPower int, inType Type) (lhs SubexAST, outType  			lhs, outType = parseDestructure(l, ArrayValuesStructure, inType)  		case '#':  			lhs, outType = parseDestructure(l, MapStructure, inType) +		case '"': +			if inType == ValueType { +				var innerOutType Type +				lhs, innerOutType = parseSubex(l, 0, RuneType) +				if !accept(l, "\"") { +					panic("Missing matching \"") +				} +				resolveTypes(innerOutType, RuneType) +				lhs = SubexASTDestructure { +					Destructure: StringStructure, +					Structure: StringStructure, +					Content: lhs, +				} +				outType = ValueType +			} else { +				l.Rewind() +				return SubexASTEmpty{}, inType +			}  		// TODO  		// case '[':  		// 	rangeParts := parseRangeSubex(l)  		// 	lhs = SubexASTRange {rangeParts} -		case ')', ']', '"', '|', ';', '{', '+', '*', '/', '!', '=', '$': +		case ')', ']', '|', ';', '{', '+', '*', '/', '!', '=', '$':  			l.Rewind()  			return SubexASTEmpty{}, inType  		// case '=': diff --git a/subex/subexstate.go b/subex/subexstate.go index 26d7347..4f5dc19 100644 --- a/subex/subexstate.go +++ b/subex/subexstate.go @@ -424,8 +424,7 @@ type SubexIncrementNestState struct {  	next SubexState  }  func (state SubexIncrementNestState) epsilon(aux auxiliaryState) []SubexBranch { -	aux.nestingLen += 1 -	aux.nestingValue = state.keys +	aux.nesting = append(aux.nesting, state.keys)  	return []SubexBranch {{  		state: state.next,  		aux: aux, @@ -439,7 +438,7 @@ type SubexDecrementNestState struct {  	next SubexState  }  func (state SubexDecrementNestState) epsilon(aux auxiliaryState) []SubexBranch { -	aux.nestingLen -= 1 +	aux.nesting = aux.nesting[:len(aux.nesting) - 1]  	// aux.nestingValue will be set in addStates  	return []SubexBranch {{  		state: state.next, | 
