diff options
| author | Charlie Stanton <charlie@shtanton.xyz> | 2023-04-21 09:53:04 +0100 | 
|---|---|---|
| committer | Charlie Stanton <charlie@shtanton.xyz> | 2023-04-21 09:53:04 +0100 | 
| commit | f1e5bc37723a4faa30bbfeed392c31489914eb50 (patch) | |
| tree | 3515317bfd9a509d4bef0392ec0cbf3da35d71eb | |
| parent | 3cb886859e9b4df4ece183583dfd8b5ba7a59584 (diff) | |
| download | stred-go-f1e5bc37723a4faa30bbfeed392c31489914eb50.tar | |
Add subex syntax to copy across booleans, numbers, strings and values
| -rw-r--r-- | subex/parse.go | 12 | ||||
| -rw-r--r-- | subex/subexast.go | 49 | ||||
| -rw-r--r-- | subex/subexstate.go | 77 | 
3 files changed, 137 insertions, 1 deletions
| diff --git a/subex/parse.go b/subex/parse.go index 5675ae0..106663d 100644 --- a/subex/parse.go +++ b/subex/parse.go @@ -281,7 +281,7 @@ func parseSubex(l RuneReader, minPower int) SubexAST {  		case '[':  			rangeParts := parseRangeSubex(l)  			lhs = SubexASTRange {rangeParts} -		case ')', '|', ';', '{', '+', '-', '*', '/', '$': +		case ')', '|', ';', '{', '+', '-', '*', '/', '!', '$':  			l.Rewind()  			return nil  		case '=': @@ -289,6 +289,16 @@ func parseSubex(l RuneReader, minPower int) SubexAST {  			lhs = SubexASTOutput{replacement}  		case '.':  			lhs = SubexASTCopyAny{} +		case '?': +			lhs = SubexASTCopyBool{} +		case '%': +			lhs = SubexASTCopyNumber{} +		case '_': +			lhs = SubexASTCopyStringAtom{} +		case '#': +			lhs = SubexASTCopyString{} +		case ',': +			lhs = SubexASTCopyValue{}  		case '"':  			lhs = SubexASTCopyAtom {walk.StringTerminal{}}  		case '`': diff --git a/subex/subexast.go b/subex/subexast.go index 87686b1..baf7a3b 100644 --- a/subex/subexast.go +++ b/subex/subexast.go @@ -134,6 +134,55 @@ func (ast SubexASTCopyAtom) compileWith(next SubexState) SubexState {  	}  } +// Read in a single atom that must be a boolean and output it unchanged +type SubexASTCopyBool struct {} +func (ast SubexASTCopyBool) compileWith(next SubexState) SubexState { +	return &SubexCopyBoolState {next} +} + +// Read in a single atom that must be a number and output it unchanged +type SubexASTCopyNumber struct {} +func (ast SubexASTCopyNumber) compileWith(next SubexState) SubexState { +	return &SubexCopyNumberState {next} +} + +// Read in a single atom that must be a string atom and output it unchanged +type SubexASTCopyStringAtom struct {} +func (ast SubexASTCopyStringAtom) compileWith(next SubexState) SubexState { +	return &SubexCopyStringAtomState {next} +} + +// Read in a full string value and copy it out unchanged +// # is equivalent to "_{-0}" +type SubexASTCopyString struct {} +func (ast SubexASTCopyString) compileWith(next SubexState) SubexState { +	stringAtomState := &SubexCopyStringAtomState { +		next: nil, +	} +	stringContentState := &SubexGroupState { +		&SubexCopyAtomState { +			atom: walk.StringTerminal{}, +			next: next, +		}, +		stringAtomState, +	} +	stringAtomState.next = stringContentState +	return &SubexCopyAtomState { +		atom: walk.StringTerminal{}, +		next: stringContentState, +	} +} + +// Read in a value and copy it out unchanged +// , is equivalent to `null`|?|%|#|[`{}[]`] +type SubexASTCopyValue struct {} +func (ast SubexASTCopyValue) compileWith(next SubexState) SubexState { +	return &SubexGroupState { +		SubexASTCopyString{}.compileWith(next), +		&SubexCopyNonStringAtomState {next}, +	} +} +  // Read in any single Atom and output it unchanged  type SubexASTCopyAny struct {}  func (ast SubexASTCopyAny) compileWith(next SubexState) SubexState { diff --git a/subex/subexstate.go b/subex/subexstate.go index cca7a88..997e6ce 100644 --- a/subex/subexstate.go +++ b/subex/subexstate.go @@ -135,6 +135,83 @@ func (state SubexCopyAtomState) accepting(store Store, outputStack OutputStack)  	return nil  } +// Read in a boolean atom and output it +type SubexCopyBoolState struct { +	next SubexState +} +func (state SubexCopyBoolState) eat(store Store, outputStack OutputStack, char walk.Atom) []SubexBranch { +	_, isBool := char.(walk.ValueBool) +	if isBool { +		return []SubexBranch{{ +			state: state.next, +			outputStack: topAppend(outputStack, []walk.Atom{char}), +			store: store, +		}} +	} +	return nil +} +func (state SubexCopyBoolState) accepting(store Store, outputStack OutputStack) []OutputStack { +	return nil +} + +// Read in a number atom and output it +type SubexCopyNumberState struct { +	next SubexState +} +func (state SubexCopyNumberState) eat(store Store, outputStack OutputStack, char walk.Atom) []SubexBranch { +	_, isNumber := char.(walk.ValueNumber) +	if isNumber { +		return []SubexBranch{{ +			state: state.next, +			outputStack: topAppend(outputStack, []walk.Atom{char}), +			store: store, +		}} +	} +	return nil +} +func (state SubexCopyNumberState) accepting(store Store, outputStack OutputStack) []OutputStack { +	return nil +} + +// Read in a string atom and output it +type SubexCopyStringAtomState struct { +	next SubexState +} +func (state SubexCopyStringAtomState) eat(store Store, outputStack OutputStack, char walk.Atom) []SubexBranch { +	_, isStringAtom := char.(walk.StringAtom) +	if isStringAtom { +		return []SubexBranch{{ +			state: state.next, +			outputStack: topAppend(outputStack, []walk.Atom{char}), +			store: store, +		}} +	} +	return nil +} +func (state SubexCopyStringAtomState) accepting(store Store, outputStack OutputStack) []OutputStack { +	return nil +} + +// Read in an atom and copy it out as long as it is not part of a string +type SubexCopyNonStringAtomState struct { +	next SubexState +} +func (state SubexCopyNonStringAtomState) eat(store Store, outputStack OutputStack, char walk.Atom) []SubexBranch { +	_, isStringAtom := char.(walk.StringAtom) +	_, isStringTerminal := char.(walk.StringTerminal) +	if isStringAtom || isStringTerminal { +		return nil +	} +	return []SubexBranch{{ +		state: state.next, +		outputStack: topAppend(outputStack, []walk.Atom{char}), +		store: store, +	}} +} +func (state SubexCopyNonStringAtomState) accepting(store Store, outputStack OutputStack) []OutputStack { +	return nil +} +  // Read in any Atom and output it  type SubexCopyAnyState struct {  	next SubexState | 
