From dae74317d84471f6a859117fcbba1cf546be8ea1 Mon Sep 17 00:00:00 2001 From: Charlie Stanton Date: Wed, 19 Apr 2023 15:19:42 +0100 Subject: Adds parsing substitute commands, though executing them currently does nothing --- main/command.go | 8 ++++++++ main/lex.go | 27 +++++++++++++++++++++++++++ main/main.go | 5 ----- main/parse.go | 23 +++++++++++++++++++++++ subex/lex.go | 8 ++++++++ 5 files changed, 66 insertions(+), 5 deletions(-) diff --git a/main/command.go b/main/command.go index c61b0cd..8053b86 100644 --- a/main/command.go +++ b/main/command.go @@ -2,6 +2,7 @@ package main import ( "main/walk" + "main/subex" ) type PrintValueCommand struct {} @@ -103,6 +104,13 @@ func (cmd DeleteAllCommand) exec(state *ProgramState) { state.space = nil } +type SubstituteCommand struct { + subex subex.SubexState +} +func (cmd SubstituteCommand) exec(state *ProgramState) { + // TODO +} + type Command interface { exec(*ProgramState) } \ No newline at end of file diff --git a/main/lex.go b/main/lex.go index 0daf2d1..e82c309 100644 --- a/main/lex.go +++ b/main/lex.go @@ -147,6 +147,7 @@ const ( TokenNumberLiteral // A number literal TokenPatternStringIndex // A string index in a pattern TokenPatternIntegerIndex // An integer index in a pattern + TokenSubex // A subex ) type Token struct { @@ -269,6 +270,9 @@ func lexCommand(l *lexer) stateFunc { case 'i': l.emit(TokenCommand) return lexMultipleLiterals + case 's': + l.emit(TokenCommand) + return lexSubstitution case 'S': l.emit(TokenCommand) return lexBigSubstitution @@ -280,6 +284,29 @@ func lexCommand(l *lexer) stateFunc { return l.errorf("Expected command found something else") } +func lexSubstitution(l *lexer) stateFunc { + delimiter := l.next() + if delimiter == eof { + return l.errorf("Missing subex in substitution command") + } + l.emit(TokenSubstituteDelimiter) + loop: for { + r := l.next() + switch r { + case delimiter: + l.backup() + l.emit(TokenSubex) + l.next() + l.emit(TokenSubstituteDelimiter) + break loop + case eof: + return l.errorf("Missing closing substitution delimiter") + default: + } + } + return lexCommand +} + func lexBigSubstitution(l *lexer) stateFunc { delimiter := l.next() if delimiter == eof || isAlphaNumeric(delimiter) { diff --git a/main/main.go b/main/main.go index 3da414d..902c5b9 100644 --- a/main/main.go +++ b/main/main.go @@ -3,7 +3,6 @@ package main import ( "os" "bufio" - "main/subex" "main/walk" ) @@ -17,10 +16,6 @@ type ProgramState struct { } func main() { - subex.Main() -} - -func mainISH() { quiet := false var input string hasInput := false diff --git a/main/parse.go b/main/parse.go index 73c7913..bf2f0ac 100644 --- a/main/parse.go +++ b/main/parse.go @@ -5,6 +5,7 @@ import ( "strconv" "fmt" "main/walk" + "main/subex" ) type parser struct { @@ -202,6 +203,25 @@ func (p *parser) parseLiterals() (items []walk.WalkItem) { return items } +func (p *parser) parseSubex() subex.SubexState { + delim := p.next() + if delim.typ != TokenSubstituteDelimiter { + panic("Missing substitute delimiter") + } + subexProgramToken := p.next() + if subexProgramToken.typ != TokenSubex { + panic("Missing subex from substitution") + } + reader := subex.NewStringRuneReader(subexProgramToken.val) + subexAST := subex.Parse(reader) + subex := subex.CompileTransducer(subexAST) + delim = p.next() + if delim.typ != TokenSubstituteDelimiter { + panic("Missing end substitute delimiter") + } + return subex +} + func (p *parser) parseBasicCommand(commandChar rune) Command { switch commandChar { case 'p': @@ -212,6 +232,9 @@ func (p *parser) parseBasicCommand(commandChar rune) Command { return NextCommand{} case 'N': return AppendNextCommand{} + case 's': + subex := p.parseSubex() + return SubstituteCommand {subex: subex} case 'i': items := p.parseLiterals() return PrintLiteralsCommand {items: items} diff --git a/subex/lex.go b/subex/lex.go index 74bf370..0f00a99 100644 --- a/subex/lex.go +++ b/subex/lex.go @@ -22,3 +22,11 @@ func (l *StringRuneReader) Next() rune { func (l *StringRuneReader) Rewind() { l.pos -= l.width } + +func NewStringRuneReader(input string) RuneReader { + return &StringRuneReader { + input: input, + pos: 0, + width: 0, + } +} -- cgit v1.2.3