gofmt pass

This commit is contained in:
eanderton
2014-09-04 07:30:19 -04:00
parent 04b60e4f8d
commit 27416cc1b9
5 changed files with 350 additions and 353 deletions
+109 -109
View File
@@ -6,8 +6,8 @@
package jpath package jpath
import ( import (
. "github.com/pelletier/go-toml"
"fmt" "fmt"
. "github.com/pelletier/go-toml"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
@@ -27,42 +27,42 @@ const (
const ( const (
tokenError tokenType = iota tokenError tokenType = iota
tokenEOF tokenEOF
tokenKey tokenKey
tokenString tokenString
tokenFloat tokenFloat
tokenInteger tokenInteger
tokenAtCost tokenAtCost
tokenDollar tokenDollar
tokenLBracket tokenLBracket
tokenRBracket tokenRBracket
tokenDot tokenDot
tokenDotDot tokenDotDot
tokenStar tokenStar
tokenComma tokenComma
tokenColon tokenColon
tokenQuestion tokenQuestion
tokenLParen tokenLParen
tokenRParen tokenRParen
) )
var tokenTypeNames = []string{ var tokenTypeNames = []string{
"EOF", "EOF",
"Key", "Key",
"String", "String",
"Float", "Float",
"Integer", "Integer",
"@", "@",
"$", "$",
"[", "[",
"]", "]",
".", ".",
"..", "..",
"*", "*",
",", ",",
":", ":",
"?", "?",
"(", "(",
")", ")",
} }
type token struct { type token struct {
@@ -126,7 +126,7 @@ type lexer struct {
depth int depth int
line int line int
col int col int
stringTerm string stringTerm string
} }
func (l *lexer) run() { func (l *lexer) run() {
@@ -221,67 +221,67 @@ func (l *lexer) follow(next string) bool {
type stateFn func(*lexer) stateFn type stateFn func(*lexer) stateFn
func lexVoid(l *lexer) stateFn { func lexVoid(l *lexer) stateFn {
for { for {
next := l.peek() next := l.peek()
switch next { switch next {
case '$': case '$':
l.pos++ l.pos++
l.emit(tokenDollar) l.emit(tokenDollar)
continue continue
case '.': case '.':
if l.follow("..") { if l.follow("..") {
l.pos += 2 l.pos += 2
l.emit(tokenDotDot) l.emit(tokenDotDot)
} else { } else {
l.pos++ l.pos++
l.emit(tokenDot) l.emit(tokenDot)
} }
continue continue
case '@': case '@':
l.pos++ l.pos++
l.emit(tokenAtCost) l.emit(tokenAtCost)
continue continue
case '[': case '[':
l.pos++ l.pos++
l.emit(tokenLBracket) l.emit(tokenLBracket)
continue continue
case ']': case ']':
l.pos++ l.pos++
l.emit(tokenRBracket) l.emit(tokenRBracket)
continue continue
case ',': case ',':
l.pos++ l.pos++
l.emit(tokenComma) l.emit(tokenComma)
continue continue
case '*': case '*':
l.pos++ l.pos++
l.emit(tokenStar) l.emit(tokenStar)
continue continue
case '(': case '(':
l.pos++ l.pos++
l.emit(tokenLParen) l.emit(tokenLParen)
continue continue
case ')': case ')':
l.pos++ l.pos++
l.emit(tokenRParen) l.emit(tokenRParen)
continue continue
case '?': case '?':
l.pos++ l.pos++
l.emit(tokenQuestion) l.emit(tokenQuestion)
continue continue
case ':': case ':':
l.pos++ l.pos++
l.emit(tokenColon) l.emit(tokenColon)
continue continue
case '\'': case '\'':
l.ignore() l.ignore()
l.stringTerm = string(next) l.stringTerm = string(next)
return lexString return lexString
case '"': case '"':
l.ignore() l.ignore()
l.stringTerm = string(next) l.stringTerm = string(next)
return lexString return lexString
} }
if isAlphanumeric(next) { if isAlphanumeric(next) {
return lexKey return lexKey
@@ -291,7 +291,7 @@ func lexVoid(l *lexer) stateFn {
return lexNumber return lexNumber
} }
if isAlphanumeric(next) { if isAlphanumeric(next) {
return lexKey return lexKey
} }
@@ -299,28 +299,28 @@ func lexVoid(l *lexer) stateFn {
l.ignore() l.ignore()
} }
if l.next() == eof { if l.next() == eof {
break break
} }
return l.errorf("unexpected char: '%v'", next) return l.errorf("unexpected char: '%v'", next)
} }
l.emit(tokenEOF) l.emit(tokenEOF)
return nil return nil
} }
func lexKey(l *lexer) stateFn { func lexKey(l *lexer) stateFn {
for { for {
next := l.peek() next := l.peek()
if !isAlphanumeric(next) { if !isAlphanumeric(next) {
l.emit(tokenKey) l.emit(tokenKey)
return lexVoid return lexVoid
} }
if l.next() == eof { if l.next() == eof {
break break
} }
} }
l.emit(tokenEOF) l.emit(tokenEOF)
return nil return nil
} }
+2 -3
View File
@@ -1,9 +1,8 @@
package jpath package jpath
import ( import (
. "github.com/pelletier/go-toml" . "github.com/pelletier/go-toml"
"testing" "testing"
) )
func testFlow(t *testing.T, input string, expectedFlow []token) { func testFlow(t *testing.T, input string, expectedFlow []token) {
+78 -79
View File
@@ -1,7 +1,7 @@
package jpath package jpath
import ( import (
. "github.com/pelletier/go-toml" . "github.com/pelletier/go-toml"
) )
type QueryPath []PathFn type QueryPath []PathFn
@@ -9,107 +9,106 @@ type QueryPath []PathFn
type PathFn func(context interface{}, next QueryPath) type PathFn func(context interface{}, next QueryPath)
func (path QueryPath) Fn(context interface{}) { func (path QueryPath) Fn(context interface{}) {
path[0](context, path[1:]) path[0](context, path[1:])
} }
func treeValue(tree *TomlTree, key string) interface{} { func treeValue(tree *TomlTree, key string) interface{} {
return tree.GetPath([]string{key}) return tree.GetPath([]string{key})
} }
func matchKeyFn(name string) PathFn { func matchKeyFn(name string) PathFn {
return func(context interface{}, next QueryPath) { return func(context interface{}, next QueryPath) {
if tree, ok := context.(*TomlTree); ok { if tree, ok := context.(*TomlTree); ok {
item := treeValue(tree, name) item := treeValue(tree, name)
if item != nil { if item != nil {
next.Fn(item) next.Fn(item)
} }
} }
} }
} }
func matchIndexFn(idx int) PathFn { func matchIndexFn(idx int) PathFn {
return func(context interface{}, next QueryPath) { return func(context interface{}, next QueryPath) {
if arr, ok := context.([]interface{}); ok { if arr, ok := context.([]interface{}); ok {
if idx < len(arr) && idx >= 0 { if idx < len(arr) && idx >= 0 {
next.Fn(arr[idx]) next.Fn(arr[idx])
} }
} }
} }
} }
func matchSliceFn(start, end, step int) PathFn { func matchSliceFn(start, end, step int) PathFn {
return func(context interface{}, next QueryPath) { return func(context interface{}, next QueryPath) {
if arr, ok := context.([]interface{}); ok { if arr, ok := context.([]interface{}); ok {
// adjust indexes for negative values, reverse ordering // adjust indexes for negative values, reverse ordering
realStart, realEnd := start, end realStart, realEnd := start, end
if realStart < 0 { if realStart < 0 {
realStart = len(arr) + realStart realStart = len(arr) + realStart
} }
if realEnd < 0 { if realEnd < 0 {
realEnd = len(arr) + realEnd realEnd = len(arr) + realEnd
} }
if realEnd < realStart { if realEnd < realStart {
realEnd, realStart = realStart, realEnd // swap realEnd, realStart = realStart, realEnd // swap
} }
// loop and gather // loop and gather
for idx := realStart; idx < realEnd; idx += step { for idx := realStart; idx < realEnd; idx += step {
next.Fn(arr[idx]) next.Fn(arr[idx])
} }
} }
} }
} }
func matchAnyFn() PathFn { func matchAnyFn() PathFn {
return func(context interface{}, next QueryPath) { return func(context interface{}, next QueryPath) {
if tree, ok := context.(*TomlTree); ok { if tree, ok := context.(*TomlTree); ok {
for _, key := range tree.Keys() { for _, key := range tree.Keys() {
item := treeValue(tree, key) item := treeValue(tree, key)
next.Fn(item) next.Fn(item)
} }
} }
} }
} }
func matchUnionFn(union QueryPath) PathFn { func matchUnionFn(union QueryPath) PathFn {
return func(context interface{}, next QueryPath) { return func(context interface{}, next QueryPath) {
for _, fn := range union { for _, fn := range union {
fn(context, next) fn(context, next)
} }
} }
} }
func matchRecurseFn() PathFn { func matchRecurseFn() PathFn {
return func(context interface{}, next QueryPath) { return func(context interface{}, next QueryPath) {
if tree, ok := context.(*TomlTree); ok { if tree, ok := context.(*TomlTree); ok {
var visit func(tree *TomlTree) var visit func(tree *TomlTree)
visit = func(tree *TomlTree) { visit = func(tree *TomlTree) {
for _, key := range tree.Keys() { for _, key := range tree.Keys() {
item := treeValue(tree, key) item := treeValue(tree, key)
next.Fn(item) next.Fn(item)
switch node := item.(type) { switch node := item.(type) {
case *TomlTree: case *TomlTree:
visit(node) visit(node)
case []*TomlTree: case []*TomlTree:
for _, subtree := range node { for _, subtree := range node {
visit(subtree) visit(subtree)
} }
} }
} }
} }
visit(tree) visit(tree)
} }
} }
} }
func processPath(path QueryPath, context interface{}) []interface{} { func processPath(path QueryPath, context interface{}) []interface{} {
// terminate the path with a collection funciton // terminate the path with a collection funciton
result := []interface{}{} result := []interface{}{}
newPath := append(path, func(context interface{}, next QueryPath) { newPath := append(path, func(context interface{}, next QueryPath) {
result = append(result, context) result = append(result, context)
}) })
// execute the path // execute the path
newPath.Fn(context) newPath.Fn(context)
return result return result
} }
+106 -107
View File
@@ -2,14 +2,14 @@ package jpath
import ( import (
"fmt" "fmt"
"math" "math"
"strconv" "strconv"
) )
type parser struct { type parser struct {
flow chan token flow chan token
tokensBuffer []token tokensBuffer []token
path []PathFn path []PathFn
} }
type parserStateFn func(*parser) parserStateFn type parserStateFn func(*parser) parserStateFn
@@ -38,7 +38,7 @@ func (p *parser) peek() *token {
if !ok { if !ok {
return nil return nil
} }
p.backup(&tok) p.backup(&tok)
return &tok return &tok
} }
@@ -55,9 +55,8 @@ func (p *parser) getToken() *token {
return &tok return &tok
} }
func (p *parser) appendPath(fn PathFn) { func (p *parser) appendPath(fn PathFn) {
p.path = append(p.path, fn) p.path = append(p.path, fn)
} }
func parseStart(p *parser) parserStateFn { func parseStart(p *parser) parserStateFn {
@@ -67,29 +66,29 @@ func parseStart(p *parser) parserStateFn {
return nil return nil
} }
if tok.typ != tokenDollar { if tok.typ != tokenDollar {
p.raiseError(tok, "Expected '$' at start of expression") p.raiseError(tok, "Expected '$' at start of expression")
} }
return parseMatchExpr return parseMatchExpr
} }
func parseMatchExpr(p *parser) parserStateFn { func parseMatchExpr(p *parser) parserStateFn {
tok := p.getToken() tok := p.getToken()
switch tok.typ { switch tok.typ {
case tokenDot: case tokenDot:
p.appendPath(matchKeyFn(tok.val)) p.appendPath(matchKeyFn(tok.val))
return parseMatchExpr return parseMatchExpr
case tokenDotDot: case tokenDotDot:
p.appendPath(matchRecurseFn()) p.appendPath(matchRecurseFn())
return parseSimpleMatchExpr return parseSimpleMatchExpr
case tokenLBracket: case tokenLBracket:
return parseBracketExpr return parseBracketExpr
case tokenStar: case tokenStar:
p.appendPath(matchAnyFn()) p.appendPath(matchAnyFn())
return parseMatchExpr return parseMatchExpr
case tokenEOF: case tokenEOF:
return nil // allow EOF at this stage return nil // allow EOF at this stage
} }
p.raiseError(tok, "expected match expression") p.raiseError(tok, "expected match expression")
return nil return nil
@@ -101,124 +100,124 @@ func parseSimpleMatchExpr(p *parser) parserStateFn {
case tokenLBracket: case tokenLBracket:
return parseBracketExpr return parseBracketExpr
case tokenKey: case tokenKey:
p.appendPath(matchKeyFn(tok.val)) p.appendPath(matchKeyFn(tok.val))
return parseMatchExpr return parseMatchExpr
case tokenStar: case tokenStar:
p.appendPath(matchAnyFn()) p.appendPath(matchAnyFn())
return parseMatchExpr return parseMatchExpr
} }
p.raiseError(tok, "expected match expression") p.raiseError(tok, "expected match expression")
return nil return nil
} }
func parseBracketExpr(p *parser) parserStateFn { func parseBracketExpr(p *parser) parserStateFn {
tok := p.peek() tok := p.peek()
switch tok.typ { switch tok.typ {
case tokenInteger: case tokenInteger:
// look ahead for a ':' // look ahead for a ':'
p.getToken() p.getToken()
next := p.peek() next := p.peek()
p.backup(tok) p.backup(tok)
if next.typ == tokenColon { if next.typ == tokenColon {
return parseSliceExpr return parseSliceExpr
} }
return parseUnionExpr return parseUnionExpr
case tokenColon: case tokenColon:
return parseSliceExpr return parseSliceExpr
} }
return parseUnionExpr return parseUnionExpr
} }
func parseUnionExpr(p *parser) parserStateFn { func parseUnionExpr(p *parser) parserStateFn {
union := []PathFn{} union := []PathFn{}
for { for {
// parse sub expression // parse sub expression
tok := p.getToken() tok := p.getToken()
switch tok.typ { switch tok.typ {
case tokenInteger: case tokenInteger:
idx, _ := strconv.Atoi(tok.val) idx, _ := strconv.Atoi(tok.val)
union = append(union, matchIndexFn(idx)) union = append(union, matchIndexFn(idx))
case tokenKey: case tokenKey:
union = append(union, matchKeyFn(tok.val)) union = append(union, matchKeyFn(tok.val))
case tokenQuestion: case tokenQuestion:
return parseFilterExpr return parseFilterExpr
case tokenLParen: case tokenLParen:
return parseScriptExpr return parseScriptExpr
default: default:
p.raiseError(tok, "expected union sub expression") p.raiseError(tok, "expected union sub expression")
} }
// parse delimiter or terminator // parse delimiter or terminator
tok = p.getToken() tok = p.getToken()
switch tok.typ { switch tok.typ {
case tokenComma: case tokenComma:
continue continue
case tokenRBracket: case tokenRBracket:
break break
default: default:
p.raiseError(tok, "expected ',' or ']'") p.raiseError(tok, "expected ',' or ']'")
} }
} }
p.appendPath(matchUnionFn(union)) p.appendPath(matchUnionFn(union))
return parseMatchExpr return parseMatchExpr
} }
func parseSliceExpr(p *parser) parserStateFn { func parseSliceExpr(p *parser) parserStateFn {
// init slice to grab all elements // init slice to grab all elements
start, end, step := 0, math.MaxInt64, 1 start, end, step := 0, math.MaxInt64, 1
// parse optional start // parse optional start
tok := p.getToken() tok := p.getToken()
if tok.typ == tokenInteger { if tok.typ == tokenInteger {
start, _ = strconv.Atoi(tok.val) start, _ = strconv.Atoi(tok.val)
tok = p.getToken() tok = p.getToken()
} }
if tok.typ != tokenColon { if tok.typ != tokenColon {
p.raiseError(tok, "expected ':'") p.raiseError(tok, "expected ':'")
} }
// parse optional end // parse optional end
tok = p.getToken() tok = p.getToken()
if tok.typ == tokenInteger { if tok.typ == tokenInteger {
end, _ = strconv.Atoi(tok.val) end, _ = strconv.Atoi(tok.val)
tok = p.getToken() tok = p.getToken()
} }
if tok.typ != tokenColon || tok.typ != tokenRBracket { if tok.typ != tokenColon || tok.typ != tokenRBracket {
p.raiseError(tok, "expected ']' or ':'") p.raiseError(tok, "expected ']' or ':'")
} }
// parse optional step // parse optional step
tok = p.getToken() tok = p.getToken()
if tok.typ == tokenInteger { if tok.typ == tokenInteger {
step, _ = strconv.Atoi(tok.val) step, _ = strconv.Atoi(tok.val)
if step < 0 { if step < 0 {
p.raiseError(tok, "step must be a positive value") p.raiseError(tok, "step must be a positive value")
} }
tok = p.getToken() tok = p.getToken()
} }
if tok.typ != tokenRBracket { if tok.typ != tokenRBracket {
p.raiseError(tok, "expected ']'") p.raiseError(tok, "expected ']'")
} }
p.appendPath(matchSliceFn(start, end, step)) p.appendPath(matchSliceFn(start, end, step))
return parseMatchExpr return parseMatchExpr
} }
func parseFilterExpr(p *parser) parserStateFn { func parseFilterExpr(p *parser) parserStateFn {
p.raiseError(p.peek(), "filter expressions are unsupported") p.raiseError(p.peek(), "filter expressions are unsupported")
return nil return nil
} }
func parseScriptExpr(p *parser) parserStateFn { func parseScriptExpr(p *parser) parserStateFn {
p.raiseError(p.peek(), "script expressions are unsupported") p.raiseError(p.peek(), "script expressions are unsupported")
return nil return nil
} }
func parse(flow chan token) []PathFn { func parse(flow chan token) []PathFn {
result := []PathFn{} result := []PathFn{}
parser := &parser{ parser := &parser{
flow: flow, flow: flow,
tokensBuffer: []token{}, tokensBuffer: []token{},
path: result, path: result,
} }
parser.run() parser.run()
return result return result
+55 -55
View File
@@ -2,15 +2,15 @@ package jpath
import ( import (
"fmt" "fmt"
. "github.com/pelletier/go-toml"
"testing" "testing"
. "github.com/pelletier/go-toml"
) )
func assertQuery(t *testing.T, toml, query string, ref []interface{}) { func assertQuery(t *testing.T, toml, query string, ref []interface{}) {
tree, err := Load(toml) tree, err := Load(toml)
if err != nil { if err != nil {
t.Errorf("Non-nil toml parse error: %v", err) t.Errorf("Non-nil toml parse error: %v", err)
return return
} }
_, flow := lex(query) _, flow := lex(query)
if err != nil { if err != nil {
@@ -18,65 +18,65 @@ func assertQuery(t *testing.T, toml, query string, ref []interface{}) {
return return
} }
path := parse(flow) path := parse(flow)
result := processPath(path, tree) result := processPath(path, tree)
assertValue(t, result, ref, "") assertValue(t, result, ref, "")
} }
func assertValue(t *testing.T, result, ref interface{}, location string) { func assertValue(t *testing.T, result, ref interface{}, location string) {
switch node := ref.(type) { switch node := ref.(type) {
case []interface{}: case []interface{}:
if resultNode, ok := result.([]interface{}); !ok { if resultNode, ok := result.([]interface{}); !ok {
t.Errorf("{%s} result value not of type %T: %T", t.Errorf("{%s} result value not of type %T: %T",
location, node, resultNode) location, node, resultNode)
} else { } else {
for i, v := range node { for i, v := range node {
assertValue(t, resultNode[i], v, fmt.Sprintf("%s[%d]", location, i)) assertValue(t, resultNode[i], v, fmt.Sprintf("%s[%d]", location, i))
} }
} }
case map[string]interface{}: case map[string]interface{}:
if resultNode, ok := result.(*TomlTree); !ok { if resultNode, ok := result.(*TomlTree); !ok {
t.Errorf("{%s} result value not of type %T: %T", t.Errorf("{%s} result value not of type %T: %T",
location, node, resultNode) location, node, resultNode)
} else { } else {
for k, v := range node { for k, v := range node {
assertValue(t, resultNode.GetPath([]string{k}), v, location + "." + k) assertValue(t, resultNode.GetPath([]string{k}), v, location+"."+k)
} }
} }
case int64: case int64:
if resultNode, ok := result.(int64); !ok { if resultNode, ok := result.(int64); !ok {
t.Errorf("{%s} result value not of type %T: %T", t.Errorf("{%s} result value not of type %T: %T",
location, node, resultNode) location, node, resultNode)
} else { } else {
if node != resultNode { if node != resultNode {
t.Errorf("{%s} result value does not match", location) t.Errorf("{%s} result value does not match", location)
} }
} }
case string: case string:
if resultNode, ok := result.(string); !ok { if resultNode, ok := result.(string); !ok {
t.Errorf("{%s} result value not of type %T: %T", t.Errorf("{%s} result value not of type %T: %T",
location, node, resultNode) location, node, resultNode)
} else { } else {
if node != resultNode { if node != resultNode {
t.Errorf("{%s} result value does not match", location) t.Errorf("{%s} result value does not match", location)
} }
} }
default: default:
if fmt.Sprintf("%v", node) != fmt.Sprintf("%v", ref) { if fmt.Sprintf("%v", node) != fmt.Sprintf("%v", ref) {
t.Errorf("{%s} result value does not match: %v != %v", t.Errorf("{%s} result value does not match: %v != %v",
location, node, ref) location, node, ref)
} }
} }
} }
func TestQueryRoot(t *testing.T) { func TestQueryRoot(t *testing.T) {
assertQuery(t, assertQuery(t,
"a = 42", "a = 42",
"$", "$",
[]interface{}{ []interface{}{
map[string]interface{}{ map[string]interface{}{
"a": int64(42), "a": int64(42),
}, },
}) })
} }
/* /*