summaryrefslogtreecommitdiff
path: root/conf
diff options
context:
space:
mode:
Diffstat (limited to 'conf')
-rw-r--r--conf/parser.go95
-rw-r--r--conf/scanner.go49
2 files changed, 131 insertions, 13 deletions
diff --git a/conf/parser.go b/conf/parser.go
index 4f58713..3d584f6 100644
--- a/conf/parser.go
+++ b/conf/parser.go
@@ -1,8 +1,12 @@
// grammar of the config file
//
+// Notes: We parse exactly three modules ("input", "filter", "output")
+// in our configuration. Each module consists of two name-object pairs
+// that are nested. We don't want to allow limitless recursion here.
+//
// config = module module module
-// module = name object
-// name = 'input' | 'filter' | 'etc.'
+// module = name object name object
+// name = 'input' | 'filter' | 'output' | etc.
// object = '{' keyvalue | keyvalue | ... '}'
// keyvalue = statement '=>' value
// statement = name | if
@@ -17,8 +21,8 @@ import (
"os"
)
-// Having a Config to Manager function could be nice?
-// Or we could just return a Manager from here.
+// Having a Config to Manager function could be nice? Or we could just
+// return a Manager from here which may be even better...
type Config struct {
}
@@ -44,6 +48,13 @@ func NewConfig(r io.Reader) *Config {
}
func (p *parser) startparsing() {
+ p.module("input")
+
+ p.module("filter")
+
+}
+
+func (p *parser) advanceOneToken(place string) {
var err error
p.last = p.cur
@@ -56,8 +67,82 @@ func (p *parser) startparsing() {
fmt.Fprintf(os.Stderr, "Error: tokentype: %v, token: %q, err: %v\n", p.cur.Type, p.cur.Lit, err)
}
-func (p *parser) module(name string) {
+func (p *parser) module(firstname string) {
+ p.advanceOneToken("module")
+
+ fmt.Fprintf(os.Stderr, "tokentype: %d, token: %q\n", p.cur.Type, p.cur.Lit)
+
+ if p.cur.Lit != firstname {
+ fmt.Fprintf(os.Stderr, "error when parsing module. We were expecting name %q but got %q at line %d offset %d.\n", firstname, p.cur.Lit, p.cur.LineNr, p.cur.Offset)
+ }
+
+ p.advanceOneToken("module")
+ if p.cur.Type != ObjectOpen {
+ fmt.Fprintf(os.Stderr, "error when parsing module. We were expecting an opening bracket but got %q at line %d offset %d.\n", p.cur.Lit, p.cur.LineNr, p.cur.Offset)
+ }
+
+ p.advanceOneToken("module")
+ if p.cur.Type != Name {
+ fmt.Fprintf(os.Stderr, "error when parsing module. We were expecting another name but got %q at line %d offset %d.\n", p.cur.Lit, p.cur.LineNr, p.cur.Offset)
+ }
+ p.object()
+
+ p.advanceOneToken("module")
+ if p.cur.Lit[0] != '}' {
+ fmt.Fprintf(os.Stderr, "error when parsing module. Was expecting a closing bracket but got %s at line %d offset %d.\n", p.cur.Lit, p.cur.LineNr, p.cur.Offset)
+ }
+
}
func (p *parser) object() {
+ p.advanceOneToken("object")
+
+ if p.cur.Lit[0] != '{' {
+ fmt.Fprintf(os.Stderr, "error when parsing object. Was expecting an opening bracket but got %s at line %d offset %d.\n", p.cur.Lit, p.cur.LineNr, p.cur.Offset)
+ }
+ // hack to deal with case where there is no white space between
+ // the delimiters.
+ if p.cur.Lit == "{}" {
+ return
+ }
+
+ for {
+ more := p.keyvalue()
+ if !more {
+ break
+ }
+ }
+}
+
+func (p *parser) keyvalue() bool {
+ p.advanceOneToken("keyvalue")
+
+ fmt.Fprintf(os.Stderr, "keyvalue: tokentype: %d, token: %q\n", p.cur.Type, p.cur.Lit)
+ if p.cur.Type != Literal {
+ fmt.Fprintf(os.Stderr, "error when parsing keyvalue. Was expecting a name but got %q at line %d offset %d.\n", p.cur.Lit, p.cur.LineNr, p.cur.Offset)
+ }
+
+ p.advanceOneToken("keyvalue")
+ if p.cur.Lit != "=>" {
+ fmt.Fprintf(os.Stderr, "error when parsing keyvalue. Was expecting a '=>' but got %q at line %d offset %d.\n", p.cur.Lit, p.cur.LineNr, p.cur.Offset)
+ }
+
+ p.advanceOneToken("keyvalue")
+ if p.cur.Type != Literal && p.cur.Type != Name {
+ fmt.Fprintf(os.Stderr, "error when parsing keyvalue. Was expecting a literal or a name but got %q at line %d offset %d.\n", p.cur.Lit, p.cur.LineNr, p.cur.Offset)
+ }
+
+ tok, err := p.s.Peek()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "error when parsing keyvalue. Got an error when checking if there are more keyvalues: %v.\n", err)
+ return false
+ }
+
+ fmt.Fprintf(os.Stderr, "peeked %q (type %d) at line %d offset %d.\n", tok.Lit, tok.Type, tok.LineNr, tok.Offset)
+ if tok.Type == ObjectClose {
+ p.advanceOneToken("keyvaluelast")
+ return false
+ }
+
+ return true
}
diff --git a/conf/scanner.go b/conf/scanner.go
index 54546aa..975a8e4 100644
--- a/conf/scanner.go
+++ b/conf/scanner.go
@@ -14,15 +14,19 @@ type tokentype int
const (
Name tokentype = iota
Literal
- DeliOpen
- DeliClose
+ ListOpen
+ ListClose
+ ObjectOpen
+ ObjectClose
+ EmptyList
+ EmptyObject
Nothing
IfStatement
)
var tokentypestrings []string = []string{Name: "Name", Literal: "Literal",
- DeliOpen: "Opening delimiter", DeliClose: "Closing delimiter",
- Nothing: "Nothing", IfStatement: "If statement"}
+ ListOpen: "List Open", ListClose: "List Close", ObjectOpen: "Object Open",
+ ObjectClose: "Object Close", Nothing: "Nothing", IfStatement: "If statement"}
func (tt tokentype) String() string {
return tokentypestrings[tt]
@@ -39,6 +43,8 @@ type scanner struct {
data []byte
offset int
curline int
+
+ peeked *token
}
func newScanner(r io.Reader) *scanner {
@@ -58,18 +64,36 @@ func newScanner(r io.Reader) *scanner {
}
func getTokenType(s []byte) tokentype {
- return Nothing
+ switch s[0] {
+ case '"', '\'':
+ return Literal
+ case '[':
+ return ListOpen
+ case ']':
+ return ListClose
+ case '{':
+ return ObjectOpen
+ case '}':
+ return ObjectClose
+ }
+
+ return Name
}
func (s *scanner) Scan() (token, error) {
processed := 0
tokenstarted := false
oldline := s.curline
+ if s.peeked != nil {
+ ret := *s.peeked
+ s.peeked = nil
+ return ret, nil
+ }
for {
r, rlen := utf8.DecodeRune(s.data[s.offset+processed:])
if r == utf8.RuneError {
if rlen == 1 {
- return token{}, fmt.Errorf("found invalid UTF8 at offset %d, before: %s", s.offset, s.data[s.offset])
+ return token{}, fmt.Errorf("found invalid UTF8 at offset %d, before: %s", s.offset, string(s.data[s.offset]))
} else if rlen == 0 {
return token{}, io.EOF
}
@@ -105,6 +129,15 @@ func (s *scanner) Scan() (token, error) {
return ret, nil
}
-func (s *scanner) peek() (tokentype, string, error) {
- return Nothing, "", nil
+func (s *scanner) Peek() (token, error) {
+ if s.peeked != nil {
+ return *s.peeked, nil
+ }
+
+ tok, err := s.Scan()
+ if err != nil {
+ return token{}, err
+ }
+ s.peeked = &tok
+ return tok, nil
}