<- Back to shtanton's homepage
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main/lex.go2
-rw-r--r--main/parse.go67
2 files changed, 53 insertions, 16 deletions
diff --git a/main/lex.go b/main/lex.go
index 2826b1e..ecb0d3d 100644
--- a/main/lex.go
+++ b/main/lex.go
@@ -179,7 +179,7 @@ func lexCommand(l *lexer) stateFunc {
case '}':
l.emit(TokenRBrace)
return lexCommand
- case 's', 'S':
+ case 's', 'S', 'f', 'F', 'l', 'L':
l.emit(TokenCommand)
return lexSubstitution
}
diff --git a/main/parse.go b/main/parse.go
index 198b746..dc86fd6 100644
--- a/main/parse.go
+++ b/main/parse.go
@@ -33,7 +33,7 @@ func (p *parser) peek() Token {
return token
}
-func (p *parser) parseSubex() subex.SubexState {
+func (p *parser) parseSubex() subex.SubexAST {
delim := p.next()
if delim.typ != TokenSubstituteDelimiter {
panic("Missing substitute delimiter")
@@ -50,12 +50,11 @@ func (p *parser) parseSubex() subex.SubexState {
}
reader := subex.NewStringRuneReader(subexProgram)
subexAST := subex.Parse(reader)
- subex := subex.CompileTransducer(subexAST)
delim = p.next()
if delim.typ != TokenSubstituteDelimiter {
panic("Missing end substitute delimiter")
}
- return subex
+ return subexAST
}
func (p *parser) parseBasicCommand(commandChar rune) Command {
@@ -70,8 +69,49 @@ func (p *parser) parseBasicCommand(commandChar rune) Command {
return NextCommand{}
case 'N':
return AppendNextCommand{}
- case 's', 'S':
- subex := p.parseSubex()
+ case 's', 'S', 'f', 'F', 'l', 'L':
+ ast := p.parseSubex()
+ switch commandChar {
+ case 'f':
+ ast = subex.SubexASTConcat {
+ First: ast,
+ Second: subex.SubexASTRepeat {
+ Content: subex.SubexASTCopyAny{},
+ Acceptable: []subex.ConvexRange{{Start: -1, End: 0}},
+ },
+ }
+ case 'F':
+ ast = subex.SubexASTConcat {
+ First: subex.SubexASTStore {
+ Slot: '_',
+ Match: ast,
+ },
+ Second: subex.SubexASTRepeat {
+ Content: subex.SubexASTCopyAny{},
+ Acceptable: []subex.ConvexRange{{Start: -1, End: 0}},
+ },
+ }
+ case 'l':
+ ast = subex.SubexASTConcat {
+ First: subex.SubexASTRepeat {
+ Content: subex.SubexASTCopyAny{},
+ Acceptable: []subex.ConvexRange{{Start: 0, End: -1}},
+ },
+ Second: ast,
+ }
+ case 'L':
+ ast = subex.SubexASTConcat {
+ First: subex.SubexASTRepeat {
+ Content: subex.SubexASTCopyAny{},
+ Acceptable: []subex.ConvexRange{{Start: 0, End: -1}},
+ },
+ Second: subex.SubexASTStore {
+ Slot: '_',
+ Match: ast,
+ },
+ }
+ }
+ subex := subex.CompileTransducer(ast)
var next Command
token := p.peek()
switch token.typ {
@@ -80,16 +120,13 @@ func (p *parser) parseBasicCommand(commandChar rune) Command {
default:
next = p.parseCommand()
}
- if (commandChar == 's') {
- return SubstituteValueCommand {
- subex: subex,
- next: next,
- }
- } else {
- return SubstitutePathCommand {
- subex: subex,
- next: next,
- }
+ switch commandChar {
+ case 's':
+ return SubstituteValueCommand {subex, next}
+ case 'S', 'f', 'F', 'l', 'L':
+ return SubstitutePathCommand {subex, next}
+ default:
+ panic("Unreachable!?!?")
}
case 'o':
return NoopCommand{}