From 3cb886859e9b4df4ece183583dfd8b5ba7a59584 Mon Sep 17 00:00:00 2001 From: Charlie Stanton Date: Thu, 20 Apr 2023 16:57:48 +0100 Subject: Adds some shorthands for substituting the beginning and end of the path register --- main/lex.go | 2 +- main/parse.go | 67 ++++++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 53 insertions(+), 16 deletions(-) (limited to 'main') 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{} -- cgit v1.2.3