From 1aa08f927c7043a643e847c434399fc76d053df0 Mon Sep 17 00:00:00 2001 From: Charlie Stanton Date: Wed, 26 Apr 2023 14:41:25 +0100 Subject: Store stred programs as a flat list of commands with no nesting, using a new jump command to simulate command blocks --- main/parse.go | 64 +++++++++++++++++++++++++---------------------------------- 1 file changed, 27 insertions(+), 37 deletions(-) (limited to 'main/parse.go') diff --git a/main/parse.go b/main/parse.go index 1972b66..ef50e81 100644 --- a/main/parse.go +++ b/main/parse.go @@ -57,18 +57,18 @@ func (p *parser) parseSubex() subex.SubexAST { return subexAST } -func (p *parser) parseBasicCommand(commandChar rune) Command { +func (p *parser) parseBasicCommand(commands []Command, commandChar rune) []Command { switch commandChar { case 'p': - return PrintValueCommand{} + return append(commands, PrintValueCommand{}) case 'd': - return DeleteValueCommand{} + return append(commands, DeleteValueCommand{}) case 'D': - return DeletePathCommand{} + return append(commands, DeletePathCommand{}) case 'n': - return NextCommand{} + return append(commands, NextCommand{}) case 'N': - return AppendNextCommand{} + return append(commands, AppendNextCommand{}) case 's', 'S', 'f', 'F', 'l', 'L', 'a', 'A': ast := p.parseSubex() switch commandChar { @@ -120,77 +120,67 @@ func (p *parser) parseBasicCommand(commandChar rune) Command { } } subex := subex.CompileTransducer(ast) - var next Command - token := p.peek() - switch token.typ { - case TokenEOF, TokenRBrace: - next = NoopCommand{} - default: - next = p.parseCommand() - } switch commandChar { case 's', 'a': - return SubstituteValueCommand {subex, next} + return append(commands, SubstituteValueCommand {subex}, JumpCommand {len(commands) + 3}) case 'S', 'f', 'F', 'l', 'L', 'A': - return SubstitutePathCommand {subex, next} + return append(commands, SubstitutePathCommand {subex}, JumpCommand {len(commands) + 3}) default: panic("Unreachable!?!?") } case 'o': - return NoopCommand{} + return append(commands, NoopCommand{}) case 'x': - return SwapXRegCommand{} + return append(commands, SwapXRegCommand{}) case 'X': - return AppendXRegCommand{} + return append(commands, AppendXRegCommand{}) case 'y': - return SwapYRegCommand{} + return append(commands, SwapYRegCommand{}) case 'Y': - return AppendYRegCommand{} + return append(commands, AppendYRegCommand{}) case 'z': - return SwapZRegCommand{} + return append(commands, SwapZRegCommand{}) case 'Z': - return AppendZRegCommand{} + return append(commands, AppendZRegCommand{}) case 'k': - return SwapPathCommand{} + return append(commands, SwapPathCommand{}) case 'K': - return AppendPathCommand{} + return append(commands, AppendPathCommand{}) default: panic("Invalid command") } } -func (p *parser) parseCommand() Command { +func (p *parser) parseCommand(commands []Command) []Command { token := p.next() switch token.typ { case TokenLBrace: - commands := p.parseCommands() + jumpToBlockCommand := &JumpCommand{0} + commands = append(commands, JumpCommand {len(commands) + 2}, jumpToBlockCommand) + commands = p.parseCommands(commands) if p.next().typ != TokenRBrace { panic("Missing matching }") } - return SequenceCommand {commands} + jumpToBlockCommand.destination = len(commands) + return commands case TokenCommand: commandChar, _, err := strings.NewReader(token.val).ReadRune() if err != nil { panic("Error reading a command character!?") } - return p.parseBasicCommand(commandChar) + return p.parseBasicCommand(commands, commandChar) default: panic("Invalid token, expected command") } } -func (p *parser) parseCommands() []Command { - var commands []Command +func (p *parser) parseCommands(commands []Command) []Command { for { nextToken := p.peek() if nextToken.typ == TokenEOF || nextToken.typ == TokenRBrace { return commands } - commands = append(commands, p.parseCommand()) - endToken := p.peek() - if endToken.typ == TokenEOF || endToken.typ == TokenRBrace { - return commands - } + commands = p.parseCommand(commands) } } @@ -198,5 +188,5 @@ func Parse(tokens chan Token) []Command { p := parser { tokenStream: tokens, } - return p.parseCommands() + return p.parseCommands(nil) } -- cgit v1.2.3