<- Back to shtanton's homepage
aboutsummaryrefslogtreecommitdiff
path: root/subex
diff options
context:
space:
mode:
authorCharlie Stanton <charlie@shtanton.xyz>2023-04-21 09:53:04 +0100
committerCharlie Stanton <charlie@shtanton.xyz>2023-04-21 09:53:04 +0100
commitf1e5bc37723a4faa30bbfeed392c31489914eb50 (patch)
tree3515317bfd9a509d4bef0392ec0cbf3da35d71eb /subex
parent3cb886859e9b4df4ece183583dfd8b5ba7a59584 (diff)
downloadstred-go-f1e5bc37723a4faa30bbfeed392c31489914eb50.tar
Add subex syntax to copy across booleans, numbers, strings and values
Diffstat (limited to 'subex')
-rw-r--r--subex/parse.go12
-rw-r--r--subex/subexast.go49
-rw-r--r--subex/subexstate.go77
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