<- Back to shtanton's homepage
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharlie Stanton <charlie@shtanton.xyz>2023-04-21 11:19:18 +0100
committerCharlie Stanton <charlie@shtanton.xyz>2023-04-21 11:19:18 +0100
commit184118c1522ee4e78a0588fcac8eb235f512b599 (patch)
treecf32b7fff7e820e0b81e6975fee661f554c5c717
parent80e7fd0626bfb98f8c1b7f69726d88f8cfa3e4fc (diff)
downloadstred-go-184118c1522ee4e78a0588fcac8eb235f512b599.tar
Add :xyz: replacement syntax that removes whatever is before it and inserts whatever is inside it
-rw-r--r--subex/parse.go20
-rw-r--r--subex/subexast.go13
-rw-r--r--subex/subexstate.go13
3 files changed, 41 insertions, 5 deletions
diff --git a/subex/parse.go b/subex/parse.go
index 52488a7..4e7a3f6 100644
--- a/subex/parse.go
+++ b/subex/parse.go
@@ -166,7 +166,7 @@ func parseReplacement(l RuneReader) (output []OutputContent) {
switch r {
case eof:
panic("Missing closing \"")
- case '=', '^':
+ case '=', '^', ':':
break loop
case '$':
slot := l.Next()
@@ -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 '=':
@@ -358,9 +358,19 @@ func parseSubex(l RuneReader, minPower int) SubexAST {
if slot == eof {
panic("Missing slot character")
}
- lhs = SubexASTStore{
- Match: lhs,
- Slot: slot,
+ if slot == '_' {
+ lhs = SubexASTDiscard {lhs}
+ } else {
+ lhs = SubexASTStore{
+ Match: lhs,
+ Slot: slot,
+ }
+ }
+ case r == ':' && minPower <= 4:
+ replacement := parseReplacement(l)
+ lhs = SubexASTConcat {
+ SubexASTDiscard {lhs},
+ SubexASTOutput {replacement},
}
case r == '|' && minPower <= 8:
rhs := parseSubex(l, 9)
diff --git a/subex/subexast.go b/subex/subexast.go
index ee7a959..dd98aa9 100644
--- a/subex/subexast.go
+++ b/subex/subexast.go
@@ -359,3 +359,16 @@ func (ast SubexASTEmpty) compileWith(next SubexState) SubexState {
func (ast SubexASTEmpty) String() string {
return "()"
}
+
+// Discards the output from the content subex
+type SubexASTDiscard struct {
+ Content SubexAST
+}
+func (ast SubexASTDiscard) compileWith(next SubexState) SubexState {
+ return &SubexCaptureBeginState {
+ next: ast.Content.compileWith(&SubexDiscardState {next}),
+ }
+}
+func (ast SubexASTDiscard) String() string {
+ return fmt.Sprintf("(%v)$_", ast.Content)
+}
diff --git a/subex/subexstate.go b/subex/subexstate.go
index 997e6ce..b5e1e9b 100644
--- a/subex/subexstate.go
+++ b/subex/subexstate.go
@@ -36,6 +36,19 @@ func (state SubexCaptureBeginState) accepting(store Store, outputStack OutputSta
return state.next.accepting(store, outputStack.push(nil))
}
+// Discard the top of the OutputStack
+type SubexDiscardState struct {
+ next SubexState
+}
+func (state SubexDiscardState) eat(store Store, outputStack OutputStack, char walk.Atom) []SubexBranch {
+ _, newStack := outputStack.pop()
+ return state.next.eat(store, newStack, char)
+}
+func (state SubexDiscardState) accepting(store Store, outputStack OutputStack) []OutputStack {
+ _, newStack := outputStack.pop()
+ return state.next.accepting(store, newStack)
+}
+
// Pop the top of the OutputStack which contains the stuff outputted since the start of the store
// This outputted data gets stored in a slot
type SubexStoreEndState struct {