Browse Source

Merge b15ecded88 into bb200ec39b

pull/19/merge
Brett Langdon 11 years ago
parent
commit
9ae48d066b
8 changed files with 54 additions and 17 deletions
  1. +3
    -0
      README.md
  2. +4
    -0
      example/example.cfg
  3. +6
    -1
      forge.go
  4. +5
    -0
      forge_test.go
  5. +4
    -1
      parser.go
  6. +14
    -0
      scanner.go
  7. +1
    -0
      test.cfg
  8. +17
    -15
      token/token.go

+ 3
- 0
README.md View File

@ -23,6 +23,9 @@ You can see example usage in the `example` folder.
# Global directives # Global directives
global = "global value"; global = "global value";
# Pull in the "PATH" environment variable
path_env = $PATH;
# Primary section # Primary section
primary { primary {
string = "primary string value"; string = "primary string value";


+ 4
- 0
example/example.cfg View File

@ -1,5 +1,9 @@
# Global stuff # Global stuff
global = "global value"; global = "global value";
# Pull in the "PATH" environment variable
path_env = $PATH;
# Primary stuff # Primary stuff
primary { primary {
string = "primary string value"; string = "primary string value";


+ 6
- 1
forge.go View File

@ -34,7 +34,8 @@
// FLOAT: ('-')? NUMBERS '.' NUMBERS // FLOAT: ('-')? NUMBERS '.' NUMBERS
// STRING: ['"] .* ['"] // STRING: ['"] .* ['"]
// REFERENCE: (IDENTIFIER)? ('.' IDENTIFIER)+ // REFERENCE: (IDENTIFIER)? ('.' IDENTIFIER)+
// VALUE: BOOL | NULL | INTEGER | FLOAT | STRING | REFERENCE
// ENVIRONMENT: '$' IDENTIFIER
// VALUE: BOOL | NULL | INTEGER | FLOAT | STRING | REFERENCE | ENVIRONMENT
// //
// INCLUDE: 'include ' STRING ';' // INCLUDE: 'include ' STRING ';'
// DIRECTIVE: (IDENTIFIER '=' VALUE | INCLUDE) ';' // DIRECTIVE: (IDENTIFIER '=' VALUE | INCLUDE) ';'
@ -62,6 +63,10 @@
// * Local reference: // * Local reference:
// An identifier which main contain periods which starts with a period, the references // An identifier which main contain periods which starts with a period, the references
// are resolved from the settings current section (e.g. .value, .sub_section.value) // are resolved from the settings current section (e.g. .value, .sub_section.value)
// * Environment:
// An environment is a way to pull in environment variables into your config. Environment variables
// are identifiers which start with a dollar sign (e.g. $PATH). Environment variables are always
// represented as strings and are evaluated at parse time.
// //
// Directives // Directives
// * Comment: // * Comment:


+ 5
- 0
forge_test.go View File

@ -3,6 +3,7 @@ package forge_test
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"os"
"testing" "testing"
"github.com/brettlangdon/forge" "github.com/brettlangdon/forge"
@ -38,12 +39,15 @@ secondary {
primary_sub_key = primary.sub.key; primary_sub_key = primary.sub.key;
another_again = .another; # References secondary.another another_again = .another; # References secondary.another
_under = 50; _under = 50;
path = $PATH;
} }
`) `)
var testConfigString = string(testConfigBytes) var testConfigString = string(testConfigBytes)
var testConfigReader = bytes.NewReader(testConfigBytes) var testConfigReader = bytes.NewReader(testConfigBytes)
var expectedPath = os.Getenv("PATH")
func assertEqual(a interface{}, b interface{}, t *testing.T) { func assertEqual(a interface{}, b interface{}, t *testing.T) {
if a != b { if a != b {
t.Fatal(fmt.Sprintf("'%v' != '%v'", a, b)) t.Fatal(fmt.Sprintf("'%v' != '%v'", a, b))
@ -80,6 +84,7 @@ func assertDirectives(values map[string]interface{}, t *testing.T) {
assertEqual(secondary["primary_sub_key"], "primary sub key value", t) assertEqual(secondary["primary_sub_key"], "primary sub key value", t)
assertEqual(secondary["another_again"], "secondary another value", t) assertEqual(secondary["another_again"], "secondary another value", t)
assertEqual(secondary["_under"], int64(50), t) assertEqual(secondary["_under"], int64(50), t)
assertEqual(secondary["path"], expectedPath, t)
} }
func TestParseBytes(t *testing.T) { func TestParseBytes(t *testing.T) {


+ 4
- 1
parser.go View File

@ -150,9 +150,12 @@ func (parser *Parser) parseSetting(name string) error {
} }
value = reference value = reference
readNext = false readNext = false
case token.ENVIRONMENT:
var envVal = os.Getenv(parser.curTok.Literal)
value = NewString(envVal)
default: default:
return parser.syntaxError( return parser.syntaxError(
fmt.Sprintf("expected STRING, INTEGER, FLOAT, BOOLEAN or IDENTIFIER, instead found %s", parser.curTok.ID),
fmt.Sprintf("expected STRING, INTEGER, FLOAT, BOOLEAN, IDENTIFIER or ENVIRONMENT, instead found %s", parser.curTok.ID),
) )
} }


+ 14
- 0
scanner.go View File

@ -171,6 +171,18 @@ func (scanner *Scanner) parseComment() {
scanner.readRune() scanner.readRune()
} }
func (scanner *Scanner) parseEnvironment() {
scanner.curTok.ID = token.ENVIRONMENT
scanner.curTok.Literal = ""
for {
scanner.readRune()
if !isLetter(scanner.curCh) && scanner.curCh != '_' {
break
}
scanner.curTok.Literal += string(scanner.curCh)
}
}
func (scanner *Scanner) skipWhitespace() { func (scanner *Scanner) skipWhitespace() {
for { for {
scanner.readRune() scanner.readRune()
@ -200,6 +212,8 @@ func (scanner *Scanner) NextToken() token.Token {
scanner.parseNumber(false) scanner.parseNumber(false)
case ch == '#': case ch == '#':
scanner.parseComment() scanner.parseComment()
case ch == '$':
scanner.parseEnvironment()
case ch == eof: case ch == eof:
scanner.curTok.ID = token.EOF scanner.curTok.ID = token.EOF
scanner.curTok.Literal = "EOF" scanner.curTok.Literal = "EOF"


+ 1
- 0
test.cfg View File

@ -27,4 +27,5 @@ secondary {
primary_sub_key = primary.sub.key; primary_sub_key = primary.sub.key;
another_again = .another; # References secondary.another another_again = .another; # References secondary.another
_under = 50; _under = 50;
path = $PATH;
} }

+ 17
- 15
token/token.go View File

@ -29,6 +29,7 @@ const (
PERIOD PERIOD
IDENTIFIER IDENTIFIER
ENVIRONMENT
BOOLEAN BOOLEAN
INTEGER INTEGER
FLOAT FLOAT
@ -39,21 +40,22 @@ const (
) )
var tokenNames = [...]string{ var tokenNames = [...]string{
ILLEGAL: "ILLEGAL",
EOF: "EOF",
LBRACKET: "LBRACKET",
RBRACKET: "RBRACKET",
EQUAL: "EQUAL",
SEMICOLON: "SEMICOLON",
PERIOD: "PERIOD",
IDENTIFIER: "IDENTIFIER",
BOOLEAN: "BOOLEAN",
INTEGER: "INTEGER",
FLOAT: "FLOAT",
STRING: "STRING",
NULL: "NULL",
COMMENT: "COMMENT",
INCLUDE: "INCLUDE",
ILLEGAL: "ILLEGAL",
EOF: "EOF",
LBRACKET: "LBRACKET",
RBRACKET: "RBRACKET",
EQUAL: "EQUAL",
SEMICOLON: "SEMICOLON",
PERIOD: "PERIOD",
IDENTIFIER: "IDENTIFIER",
ENVIRONMENT: "ENVIRONMENT",
BOOLEAN: "BOOLEAN",
INTEGER: "INTEGER",
FLOAT: "FLOAT",
STRING: "STRING",
NULL: "NULL",
COMMENT: "COMMENT",
INCLUDE: "INCLUDE",
} }
func (this TokenID) String() string { func (this TokenID) String() string {


Loading…
Cancel
Save