Swap input output files, allow multiple input, fix string parsing

- Swapped the input filename and output filename on the command line so
  multiple input files could be passed.
- Implemented appending configs when reading multiple input files.  Only
  lables, ranges, and segments are updated.  All other config settings
  are taken from the first input file.
- Fixed string parsing to allow escaping quotes inside a string.
This commit is contained in:
Zorchenhimer 2026-01-10 13:37:05 -05:00
parent 2310b042b0
commit 3406122170
Signed by: Zorchenhimer
GPG Key ID: 70A1AB767AAB9C20
4 changed files with 63 additions and 16 deletions

View File

@ -10,11 +10,11 @@ import (
)
type Arguments struct {
Input string `arg:"positional,required"`
Output string `arg:"positional"`
Output string `arg:"positional,required"`
Input []string `arg:"positional,required"`
RamStart int `arg:"--ram-start" default:"0x5000"`
RomStart int `arg:"--rom-start" default:"0xE000"`
RamStart int `arg:"--ram-start" default:"0x6000"`
RomStart int `arg:"--rom-start" default:"0x8000"`
}
func main() {
@ -29,20 +29,41 @@ func main() {
}
func run(args *Arguments) error {
input, err := os.ReadFile(args.Input)
if err != nil {
return err
var config *dasmlbl.Config
var err error
for _, infile := range args.Input {
input, err := os.ReadFile(infile)
if err != nil {
return err
}
l, ch := dasmlbl.NewLexer(string(input))
go l.Run()
parser := dasmlbl.NewParser(ch)
cfg, err := parser.Run()
if err != nil {
fmt.Printf("[%s] %s\n", infile, err)
}
if config == nil {
config = cfg
} else {
config.Append(cfg)
}
}
l, ch := dasmlbl.NewLexer(string(input))
go l.Run()
parser := dasmlbl.NewParser(ch)
config, err := parser.Run()
if err != nil {
fmt.Println(err)
if config == nil {
return fmt.Errorf("no configs parsed")
}
//input, err := os.ReadFile(args.Input)
//if err != nil {
// return err
//}
var output *os.File
if args.Output == "" {
output = os.Stdout

View File

@ -30,6 +30,12 @@ type Config struct {
Segments []Segment
}
func (c *Config) Append(other *Config) {
c.Labels = append(c.Labels, other.Labels...)
c.Ranges = append(c.Ranges, other.Ranges...)
c.Segments = append(c.Segments, other.Segments...)
}
type Label struct {
Name string
Address int

20
lex.go
View File

@ -61,6 +61,19 @@ func (l *Lexer) next() rune {
return r
}
func (l *Lexer) peek() rune {
if l.pos >= len(l.input) {
l.width = 0
return unicode_EOF
}
r, size := utf8.DecodeRuneInString(l.input[l.pos:])
if size == 0 {
panic(fmt.Sprintf("zero width at %d", l.pos))
}
return r
}
func (l *Lexer) backup() {
l.pos -= l.width
}
@ -177,6 +190,13 @@ func lexString(l *Lexer) stateFn {
l.items <- LexItem{lex_Error, "EOF before string end"}
return nil
}
if r == '\\' && l.peek() == '"' {
r = l.next()
//fmt.Printf("consuming %c\n", r) // consume
continue
}
if r == '"' {
break
}

View File

@ -139,7 +139,7 @@ func (p *Parser) parseRange() error {
itm = p.next()
if itm.typ != lex_Semicolon {
return fmt.Errorf("missing semicolon")
return fmt.Errorf("[parseRange] missing semicolon")
}
}
@ -213,7 +213,7 @@ func (p *Parser) parseLabel() error {
itm = p.next()
if itm.typ != lex_Semicolon {
return fmt.Errorf("missing semicolon")
return fmt.Errorf("[parseLabel] missing semicolon; %#v", lbl)
}
}