From f1e5bc37723a4faa30bbfeed392c31489914eb50 Mon Sep 17 00:00:00 2001 From: Charlie Stanton Date: Fri, 21 Apr 2023 09:53:04 +0100 Subject: Add subex syntax to copy across booleans, numbers, strings and values --- subex/parse.go | 12 ++++++++- subex/subexast.go | 49 ++++++++++++++++++++++++++++++++++ subex/subexstate.go | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+), 1 deletion(-) 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 -- cgit v1.2.3