diff options
| author | Charlie Stanton <charlie@shtanton.xyz> | 2023-04-20 12:05:39 +0100 | 
|---|---|---|
| committer | Charlie Stanton <charlie@shtanton.xyz> | 2023-04-20 12:05:39 +0100 | 
| commit | e2774a2ca2d58d4dd507b210d4a62a23a538e833 (patch) | |
| tree | 4341ba920ebf1d1893a73d37f613bc772c331f73 | |
| parent | c1c33227ab72de1e5f21a08ee74c3df667148343 (diff) | |
| download | stred-go-e2774a2ca2d58d4dd507b210d4a62a23a538e833.tar | |
Adds a substitute path command: S
| -rw-r--r-- | main/command.go | 43 | ||||
| -rw-r--r-- | main/lex.go | 31 | ||||
| -rw-r--r-- | 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{} | 
