Browse Source

add include directive

pull/16/head
Brett Langdon 11 years ago
parent
commit
324f5f4f64
6 changed files with 61 additions and 1 deletions
  1. +7
    -0
      README.md
  2. +7
    -0
      config/section.go
  3. +2
    -0
      example/example.cfg
  4. +37
    -1
      parser/parser.go
  5. +2
    -0
      token/tokenid.go
  6. +6
    -0
      token/tokenizer.go

+ 7
- 0
README.md View File

@ -32,6 +32,8 @@ second {
key = "value";
global_reference = sub_settings.sub_float;
local_reference = .key; # References second.key
include "/path/to/other/settings/*.cfg";
}
```
@ -43,6 +45,11 @@ Sections (basically a map) is formatted as the section name with the section's s
Comments start with a pound sign `#` and end with a newline. A comment can exist on the same line as settings/sections, but the comment must end the line.
Includes are allowed simply by using the directive `include` followed by a string pointing to the location of the file(s) you want to include.
`include` uses go's [filepath.Match](http://golang.org/pkg/path/filepath/#Glob) functionality to find all files matching the provided pattern.
Each file is included directly where it's `include` statement is called from.
`include "/etc/app/*.cfg";`
## Data types
### Boolean


+ 7
- 0
config/section.go View File

@ -6,6 +6,7 @@ type SectionValue struct {
Name string
Value map[string]ConfigValue
Comments []string
Includes []string
}
func NewNamedSection(name string) SectionValue {
@ -13,6 +14,7 @@ func NewNamedSection(name string) SectionValue {
Name: name,
Value: make(map[string]ConfigValue),
Comments: make([]string, 0),
Includes: make([]string, 0),
}
}
@ -20,6 +22,7 @@ func NewAnonymousSection() SectionValue {
return SectionValue{
Value: make(map[string]ConfigValue),
Comments: make([]string, 0),
Includes: make([]string, 0),
}
}
@ -30,6 +33,10 @@ func (this SectionValue) AddComment(comment string) {
this.Comments = append(this.Comments, comment)
}
func (this SectionValue) AddInclude(include string) {
this.Includes = append(this.Includes, include)
}
func (this SectionValue) Set(name string, value ConfigValue) {
this.Value[name] = value
}


+ 2
- 0
example/example.cfg View File

@ -8,6 +8,8 @@ primary {
boolean = true;
negative = FALSE;
nothing = NULL;
# Include external files
include "./include*.cfg";
# Primary-sub stuff
sub {
key = "primary sub key value";


+ 37
- 1
parser/parser.go View File

@ -5,6 +5,7 @@ import (
"fmt"
"io"
"os"
"path/filepath"
"strconv"
"strings"
@ -167,7 +168,7 @@ func (this *Parser) parseSetting(name string) error {
read_next = false
default:
return this.SyntaxError(
fmt.Sprintf("expected STRING, INTEGER or FLOAT, instead found %s", this.cur_tok.ID),
fmt.Sprintf("expected STRING, INTEGER, FLOAT, BOOLEAN or IDENTIFIER, instead found %s", this.cur_tok.ID),
)
}
@ -184,6 +185,39 @@ func (this *Parser) parseSetting(name string) error {
return nil
}
func (this *Parser) parseInclude() error {
if this.cur_tok.ID != token.STRING {
msg := fmt.Sprintf("expected STRING instead found '%s'", this.cur_tok.ID)
return this.SyntaxError(msg)
}
pattern := this.cur_tok.Literal
this.readToken()
if this.cur_tok.ID != token.SEMICOLON {
msg := fmt.Sprintf("expected ';' instead found '%s'", this.cur_tok.Literal)
return this.SyntaxError(msg)
}
filenames, err := filepath.Glob(pattern)
if err != nil {
return err
}
old_tokenizer := this.tokenizer
for _, filename := range filenames {
reader, err := os.Open(filename)
if err != nil {
return err
}
this.cur_section.AddInclude(filename)
this.tokenizer = token.NewTokenizer(reader)
this.Parse()
}
fmt.Println(this.cur_section.Includes)
this.tokenizer = old_tokenizer
this.readToken()
return nil
}
func (this *Parser) parseSection(name string) error {
section := config.NewNamedSection(name)
this.cur_section.Set(name, section)
@ -215,6 +249,8 @@ func (this *Parser) Parse() error {
switch tok.ID {
case token.COMMENT:
this.cur_section.AddComment(tok.Literal)
case token.INCLUDE:
this.parseInclude()
case token.IDENTIFIER:
if this.cur_tok.ID == token.LBRACKET {
err := this.parseSection(tok.Literal)


+ 2
- 0
token/tokenid.go View File

@ -19,6 +19,7 @@ const (
STRING
NULL
COMMENT
INCLUDE
)
var tokenNames = [...]string{
@ -36,6 +37,7 @@ var tokenNames = [...]string{
STRING: "STRING",
NULL: "NULL",
COMMENT: "COMMENT",
INCLUDE: "INCLUDE",
}
func (this TokenID) String() string {


+ 6
- 0
token/tokenizer.go View File

@ -29,6 +29,10 @@ func isNull(str string) bool {
return strings.ToLower(str) == "null"
}
func isInclude(str string) bool {
return strings.ToLower(str) == "include"
}
type Tokenizer struct {
cur_line int
cur_col int
@ -86,6 +90,8 @@ func (this *Tokenizer) parseIdentifier() {
this.cur_tok.ID = BOOLEAN
} else if isNull(this.cur_tok.Literal) {
this.cur_tok.ID = NULL
} else if isInclude(this.cur_tok.Literal) {
this.cur_tok.ID = INCLUDE
}
}


Loading…
Cancel
Save