From a292c25164fa4130e609026113971be51d8116a1 Mon Sep 17 00:00:00 2001 From: Robert Lowry Date: Sat, 23 Nov 2024 12:56:30 -0600 Subject: [PATCH] symbol scanner: ignore symbols inside for loops --- compile.go | 5 ++--- symbol_scanner.go | 45 +++++++++++++++++++++++++++++------------- symbol_scanner_test.go | 19 ++++++++++++++++++ 3 files changed, 52 insertions(+), 17 deletions(-) diff --git a/compile.go b/compile.go index 25e13db..bff563e 100644 --- a/compile.go +++ b/compile.go @@ -452,11 +452,10 @@ func CompileWarrior(r io.Reader, config SimulatorConfig) (WarriorData, error) { } scanner := newSymbolScanner(newBufTokenReader(tokens)) - symbols, err := scanner.ScanInput() + _, err = scanner.ScanInput() if err != nil { - return WarriorData{}, err + return WarriorData{}, fmt.Errorf("symbol scanner: %s", err) } - fmt.Println(symbols) parser := newParser(newBufTokenReader(tokens)) sourceLines, metadata, err := parser.parse() diff --git a/symbol_scanner.go b/symbol_scanner.go index 2cabedd..d847e48 100644 --- a/symbol_scanner.go +++ b/symbol_scanner.go @@ -5,6 +5,10 @@ import ( "strings" ) +// symbol scanner accepts a tokenReader and scans for any +// equ symbols contained. Symbols defined inside for loops +// are ignored, allowing us to run the same code both before +// and after for loops have been expanded. type symbolScanner struct { lex tokenReader @@ -12,6 +16,7 @@ type symbolScanner struct { atEOF bool valBuf []token labelBuf []string + forLevel int err error symbols map[string][]token @@ -49,7 +54,7 @@ func (p *symbolScanner) next() token { // run the preprocessor func (p *symbolScanner) ScanInput() (map[string][]token, error) { - for state := preLine; state != nil; { + for state := scanLine; state != nil; { state = state(p) } if p.err != nil { @@ -69,11 +74,11 @@ func (p *symbolScanner) consume(nextState scanStateFn) scanStateFn { // run at start of each line // on text: preLabels // on other: preConsumeLine -func preLine(p *symbolScanner) scanStateFn { +func scanLine(p *symbolScanner) scanStateFn { switch p.nextToken.typ { case tokText: p.labelBuf = make([]string, 0) - return preLabels + return scanLabels default: return preConsumeLine } @@ -81,27 +86,39 @@ func preLine(p *symbolScanner) scanStateFn { // text equ: consumeValue // text op: consumLine -// text default: preLabels +// text default: scanLabels // anything else: consumeLine -func preLabels(p *symbolScanner) scanStateFn { +func scanLabels(p *symbolScanner) scanStateFn { switch p.nextToken.typ { case tokText: if p.nextToken.IsPseudoOp() { - if strings.ToLower(p.nextToken.val) == "equ" { - p.valBuf = make([]token, 0) - return p.consume(preScanValue) - } else { + opLower := strings.ToLower(p.nextToken.val) + switch opLower { + case "equ": + if p.forLevel == 0 { + p.valBuf = make([]token, 0) + return p.consume(preScanValue) + } + case "for": + p.forLevel++ + return preConsumeLine + case "rof": + if p.forLevel > 0 { + p.forLevel-- + } + return preConsumeLine + default: return preConsumeLine } } else if p.nextToken.IsOp() { return preConsumeLine } p.labelBuf = append(p.labelBuf, p.nextToken.val) - return p.consume(preLabels) + return p.consume(scanLabels) case tokComment: fallthrough case tokNewline: - return p.consume(preLabels) + return p.consume(scanLabels) case tokEOF: return nil default: @@ -112,7 +129,7 @@ func preLabels(p *symbolScanner) scanStateFn { func preConsumeLine(p *symbolScanner) scanStateFn { switch p.nextToken.typ { case tokNewline: - return p.consume(preLine) + return p.consume(scanLine) case tokError: return nil case tokEOF: @@ -123,7 +140,7 @@ func preConsumeLine(p *symbolScanner) scanStateFn { } func preScanValue(p *symbolScanner) scanStateFn { - for p.nextToken.typ != tokNewline && p.nextToken.typ != tokEOF { + for p.nextToken.typ != tokNewline && p.nextToken.typ != tokEOF && p.nextToken.typ != tokError { p.valBuf = append(p.valBuf, p.nextToken) p.next() } @@ -137,5 +154,5 @@ func preScanValue(p *symbolScanner) scanStateFn { } p.valBuf = make([]token, 0) p.labelBuf = make([]string, 0) - return p.consume(preLine) + return p.consume(scanLine) } diff --git a/symbol_scanner_test.go b/symbol_scanner_test.go index 7f98450..5f8c48f 100644 --- a/symbol_scanner_test.go +++ b/symbol_scanner_test.go @@ -35,6 +35,25 @@ func TestSymbolScanner(t *testing.T) { "test": {{tokNumber, "2"}}, }, }, + { + input: "dat 0, 0", + output: map[string][]token{}, + }, + { + input: "test\ntest2\nequ 2", + output: map[string][]token{ + "test": {{tokNumber, "2"}}, + "test2": {{tokNumber, "2"}}, + }, + }, + { + // ignore symbols inside for loops because they could be redifined. + // will just re-scan after expanding for loops + input: "test equ 2\nfor 0\nq equ 1\nrof\nfor 1\nq equ 2\nrof\n", + output: map[string][]token{ + "test": {{tokNumber, "2"}}, + }, + }, } runSymbolScannerTests(t, tests) }