Skip to content

Commit

Permalink
symbol scanner: ignore symbols inside for loops
Browse files Browse the repository at this point in the history
  • Loading branch information
bobertlo committed Nov 23, 2024
1 parent 0da8eb9 commit a292c25
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 17 deletions.
5 changes: 2 additions & 3 deletions compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
45 changes: 31 additions & 14 deletions symbol_scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ 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

nextToken token
atEOF bool
valBuf []token
labelBuf []string
forLevel int
err error

symbols map[string][]token
Expand Down Expand Up @@ -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 {
Expand All @@ -69,39 +74,51 @@ 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
}
}

// 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:
Expand All @@ -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:
Expand All @@ -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()
}
Expand All @@ -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)
}
19 changes: 19 additions & 0 deletions symbol_scanner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

0 comments on commit a292c25

Please sign in to comment.