<- Back to shtanton's homepage
aboutsummaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorCharlie Stanton <charlie@shtanton.xyz>2023-04-20 12:05:39 +0100
committerCharlie Stanton <charlie@shtanton.xyz>2023-04-20 12:05:39 +0100
commite2774a2ca2d58d4dd507b210d4a62a23a538e833 (patch)
tree4341ba920ebf1d1893a73d37f613bc772c331f73 /main
parentc1c33227ab72de1e5f21a08ee74c3df667148343 (diff)
downloadstred-go-e2774a2ca2d58d4dd507b210d4a62a23a538e833.tar
Adds a substitute path command: S
Diffstat (limited to 'main')
-rw-r--r--main/command.go43
-rw-r--r--main/lex.go31
-rw-r--r--main/parse.go22
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{}