diff options
Diffstat (limited to 'parser.go')
| -rw-r--r-- | parser.go | 49 |
1 files changed, 37 insertions, 12 deletions
@@ -48,11 +48,12 @@ func NewParser(r io.Reader) *parser { default: name = "" } - res := make(map[string]Value) + res := make(map[string]Value, len(strings)) for key, s := range strings { - res[key] = []Literal{StringLiteral(s)} + res[key] = StringLiteral(s) } - db := &Database{Strings: res, Entries: make(map[string]Entry)} + db := &Database{Strings: res, Entries: make(map[string]Entry), + CrossRefs: make(map[string]int)} return &parser{Reader: bufio.NewReader(r), lineno: 1, colno: 0, fname: name, Database: db} } @@ -229,7 +230,7 @@ func (p *parser) readNumber() NumberLiteral { return NumberLiteral(n) } -func (p *parser) readLiteral() Literal { +func (p *parser) readLiteral() Value { if ch := p.peek(); ch == '{' { return p.readBraceLiteral() } else if ch == '"' { @@ -242,16 +243,18 @@ func (p *parser) readLiteral() Literal { panic(p.NewError("Expected an identifier")) } if v, in := p.Strings[id]; in { - return VariableLiteral{id, &v} + return VarLiteral{id, &v} } else { p.Warning(fmt.Sprintf("Unknown string %q", id)) - return VariableLiteral{id, &v} + l := Value(StringLiteral("")) + return VarLiteral{id, &l} } } } -func (p *parser) readValue() (res Value) { +func (p *parser) readValue() Value { var ch rune + var res LiteralList res = append(res, p.readLiteral()) for { p.eatSpace() @@ -263,7 +266,11 @@ func (p *parser) readValue() (res Value) { break } } - return + if len(res) == 1 { + return res[0] + } else { + return res + } } func (p *parser) readIdValue() (string, Value) { @@ -297,7 +304,8 @@ func (p *parser) readOpen() rune { func (p *parser) readPreamble() { close := p.readOpen() p.eatSpace() - p.Preamble = append(p.Preamble, p.readValue()) + prb := p.Preamble.(LiteralList) + p.Preamble = append(prb, p.readValue()) p.eatSpace() if ch := p.read(); ch != close { p.unread() @@ -323,6 +331,18 @@ func (p *parser) readString() { } } +func (p *parser) checkCrossRef(id string, value Value) { + if id != "crossref" { + return + } + key := strings.ToLower(value.String()) + if _, in := p.Entries[key]; in { + p.Warning(fmt.Sprintf("Crossreference %q defined before being used", + key)) + } + p.CrossRefs[key] += 1 +} + func (p *parser) readEntry(t string) { close := p.readOpen() p.eatSpace() @@ -332,10 +352,11 @@ func (p *parser) readEntry(t string) { entry.Type = t entry.Fields = make(map[string]Value) key = strings.ToLower(key) + store := true if _, in := p.Entries[key]; in { p.Warning(fmt.Sprintf("Entry %q already defined, ignoring", key)) - return + store = false } for { @@ -354,6 +375,7 @@ func (p *parser) readEntry(t string) { p.Warning(fmt.Sprintf("Field %q already defined, ignoring", id)) } else { + p.checkCrossRef(id, value) entry.Fields[id] = value entry.FNames = append(entry.FNames, id) } @@ -363,8 +385,11 @@ func (p *parser) readEntry(t string) { panic(p.NewError(fmt.Sprintf("Expected ',' or %q", close))) } } - p.Entries[key] = entry - p.EKeys = append(p.EKeys, key) + + if store { + p.Entries[key] = entry + p.EKeys = append(p.EKeys, key) + } } func (p *parser) readDeclaration() (err error) { |
