From e2774a2ca2d58d4dd507b210d4a62a23a538e833 Mon Sep 17 00:00:00 2001 From: Charlie Stanton Date: Thu, 20 Apr 2023 12:05:39 +0100 Subject: Adds a substitute path command: S --- main/command.go | 43 ++++++++++++++++++++++++++++++++----------- main/lex.go | 31 +------------------------------ main/parse.go | 22 +++++++++++----------- 3 files changed, 44 insertions(+), 52 deletions(-) diff --git a/main/command.go b/main/command.go index 7d44309..5e77dd0 100644 --- a/main/command.go +++ b/main/command.go @@ -5,6 +5,10 @@ import ( "main/subex" ) +type Command interface { + exec(*ProgramState) +} + type PrintValueCommand struct {} func (cmd PrintValueCommand) exec(state *ProgramState) { path := walk.PathFromWalkValues(state.path) @@ -45,33 +49,50 @@ func (cmd DeleteAllCommand) exec(state *ProgramState) { state.value = nil } -type SubstituteCommand struct { - subex subex.SubexState - next Command -} -func (cmd SubstituteCommand) exec(state *ProgramState) { +func runSubex(state subex.SubexState, in []walk.WalkValue) (out []walk.WalkValue, error bool) { valueStream := make(chan walk.WalkValue) go func(in []walk.WalkValue, out chan<- walk.WalkValue) { for _, value := range in { out <- value } close(out) - }(state.value, valueStream) + }(in, valueStream) atomStream := walk.Atomise(valueStream) - atomsOut, error := subex.RunTransducer(cmd.subex, atomStream) + atomsOut, error := subex.RunTransducer(state, atomStream) if error { - return + return nil, true } valuesOut, err := walk.MemoryCompound(atomsOut) if err != nil { + return nil, true + } + return valuesOut, false +} + +type SubstituteValueCommand struct { + subex subex.SubexState + next Command +} +func (cmd SubstituteValueCommand) exec(state *ProgramState) { + newValue, err := runSubex(cmd.subex, state.value) + if err { return } - state.value = valuesOut + state.value = newValue cmd.next.exec(state) } -type Command interface { - exec(*ProgramState) +type SubstitutePathCommand struct { + subex subex.SubexState + next Command +} +func (cmd SubstitutePathCommand) exec(state *ProgramState) { + newPath, err := runSubex(cmd.subex, state.path) + if err { + return + } + state.path = newPath + cmd.next.exec(state) } type NoopCommand struct {} diff --git a/main/lex.go b/main/lex.go index e93e42a..2826b1e 100644 --- a/main/lex.go +++ b/main/lex.go @@ -113,39 +113,10 @@ type TokenType int const ( TokenErr TokenType = iota // Lexing error TokenEOF // end of file - TokenLParen // ( - TokenRParen // ) TokenLBrace // { TokenRBrace // } - TokenLBrack // [ - TokenRBrack // ] TokenCommand // A command character - TokenHash // # - TokenAt // @ - TokenDot // . - TokenAst // * - TokenBar // | - TokenOr // || - TokenAnd // && - TokenHat // ^ - TokenDollar // $ - TokenQuestion // ? - TokenHatDollar // ^$ - TokenExclamation // ! - TokenTilde // ~ - TokenDoubleQuote // " - TokenStringLiteral // A string literal, not including the " either side - TokenNullLiteral // null - TokenTrueLiteral // true - TokenFalseLiteral // false - TokenColon // : - TokenComma // , TokenSubstituteDelimiter // usually / but could be something else - TokenSubstitutePlaceholder // \1, \2 etc. - TokenTerminalLiteral // One of {, }, [, ] - TokenNumberLiteral // A number literal - TokenPatternStringIndex // A string index in a pattern - TokenPatternIntegerIndex // An integer index in a pattern TokenSubex // A subex ) @@ -208,7 +179,7 @@ func lexCommand(l *lexer) stateFunc { case '}': l.emit(TokenRBrace) return lexCommand - case 's': + case 's', 'S': l.emit(TokenCommand) return lexSubstitution } diff --git a/main/parse.go b/main/parse.go index e9dd012..7c87d15 100644 --- a/main/parse.go +++ b/main/parse.go @@ -33,13 +33,6 @@ func (p *parser) peek() Token { return token } -var segmentTokens map[TokenType]bool = map[TokenType]bool { - TokenHash: true, - TokenAt: true, - TokenDot: true, - TokenLBrack: true, -} - func (p *parser) parseSubex() subex.SubexState { delim := p.next() if delim.typ != TokenSubstituteDelimiter { @@ -69,7 +62,7 @@ func (p *parser) parseBasicCommand(commandChar rune) Command { return NextCommand{} case 'N': return AppendNextCommand{} - case 's': + case 's', 'S': subex := p.parseSubex() var next Command token := p.peek() @@ -79,9 +72,16 @@ func (p *parser) parseBasicCommand(commandChar rune) Command { default: next = p.parseCommand() } - return SubstituteCommand { - subex: subex, - next: next, + if (commandChar == 's') { + return SubstituteValueCommand { + subex: subex, + next: next, + } + } else { + return SubstitutePathCommand { + subex: subex, + next: next, + } } case 'o': return NoopCommand{} -- cgit v1.2.3