mirror of
https://github.com/johnkerl/miller.git
synced 2026-01-23 02:14:13 +00:00
Preserve regex captures across stack frames (#1447)
* privatize state.RegexCaptures * stack frame for regex captures * merge * unit-test case * docs re stack frames for regex captures * more
This commit is contained in:
parent
1ae670fd4a
commit
4053d7684c
20 changed files with 183 additions and 77 deletions
|
|
@ -25,27 +25,42 @@ type State struct {
|
|||
|
||||
// For holding "\0".."\9" between where they are set via things like
|
||||
// '$x =~ "(..)_(...)"', and interpolated via things like '$y = "\2:\1"'.
|
||||
RegexCaptures []string
|
||||
Options *cli.TOptions
|
||||
//
|
||||
// Each top-level block and user-defined function has its own captures.
|
||||
//
|
||||
// For example, in function `f()`, one can do `somevar =~ someregex`, then
|
||||
// call some function `g()` which also uses `=~`, and then when `g()` returns,
|
||||
// `f()` will have its "\1", "\2", etc intact.
|
||||
//
|
||||
// This is necessary for the stateful semantics of `=~` and "\1", "\2", etc.
|
||||
// Those are avoided when the user calls `matchx`, which is newer, and
|
||||
// stateless. However, `=~` exists in the Miller DSL and we must support it.
|
||||
regexCapturesByFrame *list.List // list of []string
|
||||
|
||||
Options *cli.TOptions
|
||||
|
||||
// StrictMode allows for runtime handling of absent-reads and untyped assignments.
|
||||
StrictMode bool
|
||||
}
|
||||
|
||||
func NewEmptyState(options *cli.TOptions, strictMode bool) *State {
|
||||
|
||||
// See lib.MakeEmptyCaptures for context.
|
||||
regexCapturesByFrame := list.New()
|
||||
regexCapturesByFrame.PushFront(lib.MakeEmptyCaptures())
|
||||
|
||||
oosvars := mlrval.NewMlrmap()
|
||||
return &State{
|
||||
Inrec: nil,
|
||||
Context: nil,
|
||||
Oosvars: oosvars,
|
||||
FilterExpression: mlrval.TRUE,
|
||||
Stack: NewStack(),
|
||||
Inrec: nil,
|
||||
Context: nil,
|
||||
Oosvars: oosvars,
|
||||
FilterExpression: mlrval.TRUE,
|
||||
Stack: NewStack(),
|
||||
regexCapturesByFrame: regexCapturesByFrame,
|
||||
|
||||
// OutputRecordsAndContexts is assigned after construction
|
||||
|
||||
// See lib.MakeEmptyCaptures for context.
|
||||
RegexCaptures: lib.MakeEmptyCaptures(),
|
||||
Options: options,
|
||||
Options: options,
|
||||
|
||||
StrictMode: strictMode,
|
||||
}
|
||||
|
|
@ -57,5 +72,25 @@ func (state *State) Update(
|
|||
) {
|
||||
state.Inrec = inrec
|
||||
state.Context = context
|
||||
state.RegexCaptures = lib.MakeEmptyCaptures()
|
||||
state.regexCapturesByFrame.Front().Value = lib.MakeEmptyCaptures()
|
||||
}
|
||||
|
||||
func (state *State) SetRegexCaptures(
|
||||
captures []string,
|
||||
) {
|
||||
state.regexCapturesByFrame.Front().Value = lib.CopyStringArray(captures)
|
||||
}
|
||||
|
||||
func (state *State) GetRegexCaptures() []string {
|
||||
regexCaptures := state.regexCapturesByFrame.Front().Value.([]string)
|
||||
return lib.CopyStringArray(regexCaptures)
|
||||
}
|
||||
|
||||
func (state *State) PushRegexCapturesFrame() {
|
||||
state.regexCapturesByFrame.PushFront(lib.MakeEmptyCaptures())
|
||||
}
|
||||
|
||||
func (state *State) PopRegexCapturesFrame() {
|
||||
// There is no PopFront
|
||||
state.regexCapturesByFrame.Remove(state.regexCapturesByFrame.Front())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue