...
1
2
3
4
5 package properties
6
7 import (
8 "fmt"
9 "runtime"
10 )
11
12 type parser struct {
13 lex *lexer
14 }
15
16 func parse(input string) (properties *Properties, err error) {
17 p := &parser{lex: lex(input)}
18 defer p.recover(&err)
19
20 properties = NewProperties()
21 key := ""
22 comments := []string{}
23
24 for {
25 token := p.expectOneOf(itemComment, itemKey, itemEOF)
26 switch token.typ {
27 case itemEOF:
28 goto done
29 case itemComment:
30 comments = append(comments, token.val)
31 continue
32 case itemKey:
33 key = token.val
34 if _, ok := properties.m[key]; !ok {
35 properties.k = append(properties.k, key)
36 }
37 }
38
39 token = p.expectOneOf(itemValue, itemEOF)
40 if len(comments) > 0 {
41 properties.c[key] = comments
42 comments = []string{}
43 }
44 switch token.typ {
45 case itemEOF:
46 properties.m[key] = ""
47 goto done
48 case itemValue:
49 properties.m[key] = token.val
50 }
51 }
52
53 done:
54 return properties, nil
55 }
56
57 func (p *parser) errorf(format string, args ...interface{}) {
58 format = fmt.Sprintf("properties: Line %d: %s", p.lex.lineNumber(), format)
59 panic(fmt.Errorf(format, args...))
60 }
61
62 func (p *parser) expectOneOf(expected ...itemType) (token item) {
63 token = p.lex.nextItem()
64 for _, v := range expected {
65 if token.typ == v {
66 return token
67 }
68 }
69 p.unexpected(token)
70 panic("unexpected token")
71 }
72
73 func (p *parser) unexpected(token item) {
74 p.errorf(token.String())
75 }
76
77
78 func (p *parser) recover(errp *error) {
79 e := recover()
80 if e != nil {
81 if _, ok := e.(runtime.Error); ok {
82 panic(e)
83 }
84 *errp = e.(error)
85 }
86 }
87
View as plain text