diff options
Diffstat (limited to 'vendor/github.com/aws/aws-sdk-go/internal/ini')
23 files changed, 2071 insertions, 0 deletions
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/ast.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/ast.go new file mode 100644 index 0000000..e83a998 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/ast.go | |||
@@ -0,0 +1,120 @@ | |||
1 | package ini | ||
2 | |||
3 | // ASTKind represents different states in the parse table | ||
4 | // and the type of AST that is being constructed | ||
5 | type ASTKind int | ||
6 | |||
7 | // ASTKind* is used in the parse table to transition between | ||
8 | // the different states | ||
9 | const ( | ||
10 | ASTKindNone = ASTKind(iota) | ||
11 | ASTKindStart | ||
12 | ASTKindExpr | ||
13 | ASTKindEqualExpr | ||
14 | ASTKindStatement | ||
15 | ASTKindSkipStatement | ||
16 | ASTKindExprStatement | ||
17 | ASTKindSectionStatement | ||
18 | ASTKindNestedSectionStatement | ||
19 | ASTKindCompletedNestedSectionStatement | ||
20 | ASTKindCommentStatement | ||
21 | ASTKindCompletedSectionStatement | ||
22 | ) | ||
23 | |||
24 | func (k ASTKind) String() string { | ||
25 | switch k { | ||
26 | case ASTKindNone: | ||
27 | return "none" | ||
28 | case ASTKindStart: | ||
29 | return "start" | ||
30 | case ASTKindExpr: | ||
31 | return "expr" | ||
32 | case ASTKindStatement: | ||
33 | return "stmt" | ||
34 | case ASTKindSectionStatement: | ||
35 | return "section_stmt" | ||
36 | case ASTKindExprStatement: | ||
37 | return "expr_stmt" | ||
38 | case ASTKindCommentStatement: | ||
39 | return "comment" | ||
40 | case ASTKindNestedSectionStatement: | ||
41 | return "nested_section_stmt" | ||
42 | case ASTKindCompletedSectionStatement: | ||
43 | return "completed_stmt" | ||
44 | case ASTKindSkipStatement: | ||
45 | return "skip" | ||
46 | default: | ||
47 | return "" | ||
48 | } | ||
49 | } | ||
50 | |||
51 | // AST interface allows us to determine what kind of node we | ||
52 | // are on and casting may not need to be necessary. | ||
53 | // | ||
54 | // The root is always the first node in Children | ||
55 | type AST struct { | ||
56 | Kind ASTKind | ||
57 | Root Token | ||
58 | RootToken bool | ||
59 | Children []AST | ||
60 | } | ||
61 | |||
62 | func newAST(kind ASTKind, root AST, children ...AST) AST { | ||
63 | return AST{ | ||
64 | Kind: kind, | ||
65 | Children: append([]AST{root}, children...), | ||
66 | } | ||
67 | } | ||
68 | |||
69 | func newASTWithRootToken(kind ASTKind, root Token, children ...AST) AST { | ||
70 | return AST{ | ||
71 | Kind: kind, | ||
72 | Root: root, | ||
73 | RootToken: true, | ||
74 | Children: children, | ||
75 | } | ||
76 | } | ||
77 | |||
78 | // AppendChild will append to the list of children an AST has. | ||
79 | func (a *AST) AppendChild(child AST) { | ||
80 | a.Children = append(a.Children, child) | ||
81 | } | ||
82 | |||
83 | // GetRoot will return the root AST which can be the first entry | ||
84 | // in the children list or a token. | ||
85 | func (a *AST) GetRoot() AST { | ||
86 | if a.RootToken { | ||
87 | return *a | ||
88 | } | ||
89 | |||
90 | if len(a.Children) == 0 { | ||
91 | return AST{} | ||
92 | } | ||
93 | |||
94 | return a.Children[0] | ||
95 | } | ||
96 | |||
97 | // GetChildren will return the current AST's list of children | ||
98 | func (a *AST) GetChildren() []AST { | ||
99 | if len(a.Children) == 0 { | ||
100 | return []AST{} | ||
101 | } | ||
102 | |||
103 | if a.RootToken { | ||
104 | return a.Children | ||
105 | } | ||
106 | |||
107 | return a.Children[1:] | ||
108 | } | ||
109 | |||
110 | // SetChildren will set and override all children of the AST. | ||
111 | func (a *AST) SetChildren(children []AST) { | ||
112 | if a.RootToken { | ||
113 | a.Children = children | ||
114 | } else { | ||
115 | a.Children = append(a.Children[:1], children...) | ||
116 | } | ||
117 | } | ||
118 | |||
119 | // Start is used to indicate the starting state of the parse table. | ||
120 | var Start = newAST(ASTKindStart, AST{}) | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/comma_token.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/comma_token.go new file mode 100644 index 0000000..0895d53 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/comma_token.go | |||
@@ -0,0 +1,11 @@ | |||
1 | package ini | ||
2 | |||
3 | var commaRunes = []rune(",") | ||
4 | |||
5 | func isComma(b rune) bool { | ||
6 | return b == ',' | ||
7 | } | ||
8 | |||
9 | func newCommaToken() Token { | ||
10 | return newToken(TokenComma, commaRunes, NoneType) | ||
11 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/comment_token.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/comment_token.go new file mode 100644 index 0000000..0b76999 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/comment_token.go | |||
@@ -0,0 +1,35 @@ | |||
1 | package ini | ||
2 | |||
3 | // isComment will return whether or not the next byte(s) is a | ||
4 | // comment. | ||
5 | func isComment(b []rune) bool { | ||
6 | if len(b) == 0 { | ||
7 | return false | ||
8 | } | ||
9 | |||
10 | switch b[0] { | ||
11 | case ';': | ||
12 | return true | ||
13 | case '#': | ||
14 | return true | ||
15 | } | ||
16 | |||
17 | return false | ||
18 | } | ||
19 | |||
20 | // newCommentToken will create a comment token and | ||
21 | // return how many bytes were read. | ||
22 | func newCommentToken(b []rune) (Token, int, error) { | ||
23 | i := 0 | ||
24 | for ; i < len(b); i++ { | ||
25 | if b[i] == '\n' { | ||
26 | break | ||
27 | } | ||
28 | |||
29 | if len(b)-i > 2 && b[i] == '\r' && b[i+1] == '\n' { | ||
30 | break | ||
31 | } | ||
32 | } | ||
33 | |||
34 | return newToken(TokenComment, b[:i], NoneType), i, nil | ||
35 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/doc.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/doc.go new file mode 100644 index 0000000..25ce0fe --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/doc.go | |||
@@ -0,0 +1,29 @@ | |||
1 | // Package ini is an LL(1) parser for configuration files. | ||
2 | // | ||
3 | // Example: | ||
4 | // sections, err := ini.OpenFile("/path/to/file") | ||
5 | // if err != nil { | ||
6 | // panic(err) | ||
7 | // } | ||
8 | // | ||
9 | // profile := "foo" | ||
10 | // section, ok := sections.GetSection(profile) | ||
11 | // if !ok { | ||
12 | // fmt.Printf("section %q could not be found", profile) | ||
13 | // } | ||
14 | // | ||
15 | // Below is the BNF that describes this parser | ||
16 | // Grammar: | ||
17 | // stmt -> value stmt' | ||
18 | // stmt' -> epsilon | op stmt | ||
19 | // value -> number | string | boolean | quoted_string | ||
20 | // | ||
21 | // section -> [ section' | ||
22 | // section' -> value section_close | ||
23 | // section_close -> ] | ||
24 | // | ||
25 | // SkipState will skip (NL WS)+ | ||
26 | // | ||
27 | // comment -> # comment' | ; comment' | ||
28 | // comment' -> epsilon | value | ||
29 | package ini | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/empty_token.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/empty_token.go new file mode 100644 index 0000000..04345a5 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/empty_token.go | |||
@@ -0,0 +1,4 @@ | |||
1 | package ini | ||
2 | |||
3 | // emptyToken is used to satisfy the Token interface | ||
4 | var emptyToken = newToken(TokenNone, []rune{}, NoneType) | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/expression.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/expression.go new file mode 100644 index 0000000..91ba2a5 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/expression.go | |||
@@ -0,0 +1,24 @@ | |||
1 | package ini | ||
2 | |||
3 | // newExpression will return an expression AST. | ||
4 | // Expr represents an expression | ||
5 | // | ||
6 | // grammar: | ||
7 | // expr -> string | number | ||
8 | func newExpression(tok Token) AST { | ||
9 | return newASTWithRootToken(ASTKindExpr, tok) | ||
10 | } | ||
11 | |||
12 | func newEqualExpr(left AST, tok Token) AST { | ||
13 | return newASTWithRootToken(ASTKindEqualExpr, tok, left) | ||
14 | } | ||
15 | |||
16 | // EqualExprKey will return a LHS value in the equal expr | ||
17 | func EqualExprKey(ast AST) string { | ||
18 | children := ast.GetChildren() | ||
19 | if len(children) == 0 || ast.Kind != ASTKindEqualExpr { | ||
20 | return "" | ||
21 | } | ||
22 | |||
23 | return string(children[0].Root.Raw()) | ||
24 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/fuzz.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/fuzz.go new file mode 100644 index 0000000..8d462f7 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/fuzz.go | |||
@@ -0,0 +1,17 @@ | |||
1 | // +build gofuzz | ||
2 | |||
3 | package ini | ||
4 | |||
5 | import ( | ||
6 | "bytes" | ||
7 | ) | ||
8 | |||
9 | func Fuzz(data []byte) int { | ||
10 | b := bytes.NewReader(data) | ||
11 | |||
12 | if _, err := Parse(b); err != nil { | ||
13 | return 0 | ||
14 | } | ||
15 | |||
16 | return 1 | ||
17 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/ini.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/ini.go new file mode 100644 index 0000000..3b0ca7a --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/ini.go | |||
@@ -0,0 +1,51 @@ | |||
1 | package ini | ||
2 | |||
3 | import ( | ||
4 | "io" | ||
5 | "os" | ||
6 | |||
7 | "github.com/aws/aws-sdk-go/aws/awserr" | ||
8 | ) | ||
9 | |||
10 | // OpenFile takes a path to a given file, and will open and parse | ||
11 | // that file. | ||
12 | func OpenFile(path string) (Sections, error) { | ||
13 | f, err := os.Open(path) | ||
14 | if err != nil { | ||
15 | return Sections{}, awserr.New(ErrCodeUnableToReadFile, "unable to open file", err) | ||
16 | } | ||
17 | defer f.Close() | ||
18 | |||
19 | return Parse(f) | ||
20 | } | ||
21 | |||
22 | // Parse will parse the given file using the shared config | ||
23 | // visitor. | ||
24 | func Parse(f io.Reader) (Sections, error) { | ||
25 | tree, err := ParseAST(f) | ||
26 | if err != nil { | ||
27 | return Sections{}, err | ||
28 | } | ||
29 | |||
30 | v := NewDefaultVisitor() | ||
31 | if err = Walk(tree, v); err != nil { | ||
32 | return Sections{}, err | ||
33 | } | ||
34 | |||
35 | return v.Sections, nil | ||
36 | } | ||
37 | |||
38 | // ParseBytes will parse the given bytes and return the parsed sections. | ||
39 | func ParseBytes(b []byte) (Sections, error) { | ||
40 | tree, err := ParseASTBytes(b) | ||
41 | if err != nil { | ||
42 | return Sections{}, err | ||
43 | } | ||
44 | |||
45 | v := NewDefaultVisitor() | ||
46 | if err = Walk(tree, v); err != nil { | ||
47 | return Sections{}, err | ||
48 | } | ||
49 | |||
50 | return v.Sections, nil | ||
51 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/ini_lexer.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/ini_lexer.go new file mode 100644 index 0000000..582c024 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/ini_lexer.go | |||
@@ -0,0 +1,165 @@ | |||
1 | package ini | ||
2 | |||
3 | import ( | ||
4 | "bytes" | ||
5 | "io" | ||
6 | "io/ioutil" | ||
7 | |||
8 | "github.com/aws/aws-sdk-go/aws/awserr" | ||
9 | ) | ||
10 | |||
11 | const ( | ||
12 | // ErrCodeUnableToReadFile is used when a file is failed to be | ||
13 | // opened or read from. | ||
14 | ErrCodeUnableToReadFile = "FailedRead" | ||
15 | ) | ||
16 | |||
17 | // TokenType represents the various different tokens types | ||
18 | type TokenType int | ||
19 | |||
20 | func (t TokenType) String() string { | ||
21 | switch t { | ||
22 | case TokenNone: | ||
23 | return "none" | ||
24 | case TokenLit: | ||
25 | return "literal" | ||
26 | case TokenSep: | ||
27 | return "sep" | ||
28 | case TokenOp: | ||
29 | return "op" | ||
30 | case TokenWS: | ||
31 | return "ws" | ||
32 | case TokenNL: | ||
33 | return "newline" | ||
34 | case TokenComment: | ||
35 | return "comment" | ||
36 | case TokenComma: | ||
37 | return "comma" | ||
38 | default: | ||
39 | return "" | ||
40 | } | ||
41 | } | ||
42 | |||
43 | // TokenType enums | ||
44 | const ( | ||
45 | TokenNone = TokenType(iota) | ||
46 | TokenLit | ||
47 | TokenSep | ||
48 | TokenComma | ||
49 | TokenOp | ||
50 | TokenWS | ||
51 | TokenNL | ||
52 | TokenComment | ||
53 | ) | ||
54 | |||
55 | type iniLexer struct{} | ||
56 | |||
57 | // Tokenize will return a list of tokens during lexical analysis of the | ||
58 | // io.Reader. | ||
59 | func (l *iniLexer) Tokenize(r io.Reader) ([]Token, error) { | ||
60 | b, err := ioutil.ReadAll(r) | ||
61 | if err != nil { | ||
62 | return nil, awserr.New(ErrCodeUnableToReadFile, "unable to read file", err) | ||
63 | } | ||
64 | |||
65 | return l.tokenize(b) | ||
66 | } | ||
67 | |||
68 | func (l *iniLexer) tokenize(b []byte) ([]Token, error) { | ||
69 | runes := bytes.Runes(b) | ||
70 | var err error | ||
71 | n := 0 | ||
72 | tokenAmount := countTokens(runes) | ||
73 | tokens := make([]Token, tokenAmount) | ||
74 | count := 0 | ||
75 | |||
76 | for len(runes) > 0 && count < tokenAmount { | ||
77 | switch { | ||
78 | case isWhitespace(runes[0]): | ||
79 | tokens[count], n, err = newWSToken(runes) | ||
80 | case isComma(runes[0]): | ||
81 | tokens[count], n = newCommaToken(), 1 | ||
82 | case isComment(runes): | ||
83 | tokens[count], n, err = newCommentToken(runes) | ||
84 | case isNewline(runes): | ||
85 | tokens[count], n, err = newNewlineToken(runes) | ||
86 | case isSep(runes): | ||
87 | tokens[count], n, err = newSepToken(runes) | ||
88 | case isOp(runes): | ||
89 | tokens[count], n, err = newOpToken(runes) | ||
90 | default: | ||
91 | tokens[count], n, err = newLitToken(runes) | ||
92 | } | ||
93 | |||
94 | if err != nil { | ||
95 | return nil, err | ||
96 | } | ||
97 | |||
98 | count++ | ||
99 | |||
100 | runes = runes[n:] | ||
101 | } | ||
102 | |||
103 | return tokens[:count], nil | ||
104 | } | ||
105 | |||
106 | func countTokens(runes []rune) int { | ||
107 | count, n := 0, 0 | ||
108 | var err error | ||
109 | |||
110 | for len(runes) > 0 { | ||
111 | switch { | ||
112 | case isWhitespace(runes[0]): | ||
113 | _, n, err = newWSToken(runes) | ||
114 | case isComma(runes[0]): | ||
115 | _, n = newCommaToken(), 1 | ||
116 | case isComment(runes): | ||
117 | _, n, err = newCommentToken(runes) | ||
118 | case isNewline(runes): | ||
119 | _, n, err = newNewlineToken(runes) | ||
120 | case isSep(runes): | ||
121 | _, n, err = newSepToken(runes) | ||
122 | case isOp(runes): | ||
123 | _, n, err = newOpToken(runes) | ||
124 | default: | ||
125 | _, n, err = newLitToken(runes) | ||
126 | } | ||
127 | |||
128 | if err != nil { | ||
129 | return 0 | ||
130 | } | ||
131 | |||
132 | count++ | ||
133 | runes = runes[n:] | ||
134 | } | ||
135 | |||
136 | return count + 1 | ||
137 | } | ||
138 | |||
139 | // Token indicates a metadata about a given value. | ||
140 | type Token struct { | ||
141 | t TokenType | ||
142 | ValueType ValueType | ||
143 | base int | ||
144 | raw []rune | ||
145 | } | ||
146 | |||
147 | var emptyValue = Value{} | ||
148 | |||
149 | func newToken(t TokenType, raw []rune, v ValueType) Token { | ||
150 | return Token{ | ||
151 | t: t, | ||
152 | raw: raw, | ||
153 | ValueType: v, | ||
154 | } | ||
155 | } | ||
156 | |||
157 | // Raw return the raw runes that were consumed | ||
158 | func (tok Token) Raw() []rune { | ||
159 | return tok.raw | ||
160 | } | ||
161 | |||
162 | // Type returns the token type | ||
163 | func (tok Token) Type() TokenType { | ||
164 | return tok.t | ||
165 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/ini_parser.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/ini_parser.go new file mode 100644 index 0000000..f997033 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/ini_parser.go | |||
@@ -0,0 +1,347 @@ | |||
1 | package ini | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "io" | ||
6 | ) | ||
7 | |||
8 | // State enums for the parse table | ||
9 | const ( | ||
10 | InvalidState = iota | ||
11 | // stmt -> value stmt' | ||
12 | StatementState | ||
13 | // stmt' -> MarkComplete | op stmt | ||
14 | StatementPrimeState | ||
15 | // value -> number | string | boolean | quoted_string | ||
16 | ValueState | ||
17 | // section -> [ section' | ||
18 | OpenScopeState | ||
19 | // section' -> value section_close | ||
20 | SectionState | ||
21 | // section_close -> ] | ||
22 | CloseScopeState | ||
23 | // SkipState will skip (NL WS)+ | ||
24 | SkipState | ||
25 | // SkipTokenState will skip any token and push the previous | ||
26 | // state onto the stack. | ||
27 | SkipTokenState | ||
28 | // comment -> # comment' | ; comment' | ||
29 | // comment' -> MarkComplete | value | ||
30 | CommentState | ||
31 | // MarkComplete state will complete statements and move that | ||
32 | // to the completed AST list | ||
33 | MarkCompleteState | ||
34 | // TerminalState signifies that the tokens have been fully parsed | ||
35 | TerminalState | ||
36 | ) | ||
37 | |||
38 | // parseTable is a state machine to dictate the grammar above. | ||
39 | var parseTable = map[ASTKind]map[TokenType]int{ | ||
40 | ASTKindStart: map[TokenType]int{ | ||
41 | TokenLit: StatementState, | ||
42 | TokenSep: OpenScopeState, | ||
43 | TokenWS: SkipTokenState, | ||
44 | TokenNL: SkipTokenState, | ||
45 | TokenComment: CommentState, | ||
46 | TokenNone: TerminalState, | ||
47 | }, | ||
48 | ASTKindCommentStatement: map[TokenType]int{ | ||
49 | TokenLit: StatementState, | ||
50 | TokenSep: OpenScopeState, | ||
51 | TokenWS: SkipTokenState, | ||
52 | TokenNL: SkipTokenState, | ||
53 | TokenComment: CommentState, | ||
54 | TokenNone: MarkCompleteState, | ||
55 | }, | ||
56 | ASTKindExpr: map[TokenType]int{ | ||
57 | TokenOp: StatementPrimeState, | ||
58 | TokenLit: ValueState, | ||
59 | TokenSep: OpenScopeState, | ||
60 | TokenWS: ValueState, | ||
61 | TokenNL: SkipState, | ||
62 | TokenComment: CommentState, | ||
63 | TokenNone: MarkCompleteState, | ||
64 | }, | ||
65 | ASTKindEqualExpr: map[TokenType]int{ | ||
66 | TokenLit: ValueState, | ||
67 | TokenWS: SkipTokenState, | ||
68 | TokenNL: SkipState, | ||
69 | }, | ||
70 | ASTKindStatement: map[TokenType]int{ | ||
71 | TokenLit: SectionState, | ||
72 | TokenSep: CloseScopeState, | ||
73 | TokenWS: SkipTokenState, | ||
74 | TokenNL: SkipTokenState, | ||
75 | TokenComment: CommentState, | ||
76 | TokenNone: MarkCompleteState, | ||
77 | }, | ||
78 | ASTKindExprStatement: map[TokenType]int{ | ||
79 | TokenLit: ValueState, | ||
80 | TokenSep: OpenScopeState, | ||
81 | TokenOp: ValueState, | ||
82 | TokenWS: ValueState, | ||
83 | TokenNL: MarkCompleteState, | ||
84 | TokenComment: CommentState, | ||
85 | TokenNone: TerminalState, | ||
86 | TokenComma: SkipState, | ||
87 | }, | ||
88 | ASTKindSectionStatement: map[TokenType]int{ | ||
89 | TokenLit: SectionState, | ||
90 | TokenOp: SectionState, | ||
91 | TokenSep: CloseScopeState, | ||
92 | TokenWS: SectionState, | ||
93 | TokenNL: SkipTokenState, | ||
94 | }, | ||
95 | ASTKindCompletedSectionStatement: map[TokenType]int{ | ||
96 | TokenWS: SkipTokenState, | ||
97 | TokenNL: SkipTokenState, | ||
98 | TokenLit: StatementState, | ||
99 | TokenSep: OpenScopeState, | ||
100 | TokenComment: CommentState, | ||
101 | TokenNone: MarkCompleteState, | ||
102 | }, | ||
103 | ASTKindSkipStatement: map[TokenType]int{ | ||
104 | TokenLit: StatementState, | ||
105 | TokenSep: OpenScopeState, | ||
106 | TokenWS: SkipTokenState, | ||
107 | TokenNL: SkipTokenState, | ||
108 | TokenComment: CommentState, | ||
109 | TokenNone: TerminalState, | ||
110 | }, | ||
111 | } | ||
112 | |||
113 | // ParseAST will parse input from an io.Reader using | ||
114 | // an LL(1) parser. | ||
115 | func ParseAST(r io.Reader) ([]AST, error) { | ||
116 | lexer := iniLexer{} | ||
117 | tokens, err := lexer.Tokenize(r) | ||
118 | if err != nil { | ||
119 | return []AST{}, err | ||
120 | } | ||
121 | |||
122 | return parse(tokens) | ||
123 | } | ||
124 | |||
125 | // ParseASTBytes will parse input from a byte slice using | ||
126 | // an LL(1) parser. | ||
127 | func ParseASTBytes(b []byte) ([]AST, error) { | ||
128 | lexer := iniLexer{} | ||
129 | tokens, err := lexer.tokenize(b) | ||
130 | if err != nil { | ||
131 | return []AST{}, err | ||
132 | } | ||
133 | |||
134 | return parse(tokens) | ||
135 | } | ||
136 | |||
137 | func parse(tokens []Token) ([]AST, error) { | ||
138 | start := Start | ||
139 | stack := newParseStack(3, len(tokens)) | ||
140 | |||
141 | stack.Push(start) | ||
142 | s := newSkipper() | ||
143 | |||
144 | loop: | ||
145 | for stack.Len() > 0 { | ||
146 | k := stack.Pop() | ||
147 | |||
148 | var tok Token | ||
149 | if len(tokens) == 0 { | ||
150 | // this occurs when all the tokens have been processed | ||
151 | // but reduction of what's left on the stack needs to | ||
152 | // occur. | ||
153 | tok = emptyToken | ||
154 | } else { | ||
155 | tok = tokens[0] | ||
156 | } | ||
157 | |||
158 | step := parseTable[k.Kind][tok.Type()] | ||
159 | if s.ShouldSkip(tok) { | ||
160 | // being in a skip state with no tokens will break out of | ||
161 | // the parse loop since there is nothing left to process. | ||
162 | if len(tokens) == 0 { | ||
163 | break loop | ||
164 | } | ||
165 | |||
166 | step = SkipTokenState | ||
167 | } | ||
168 | |||
169 | switch step { | ||
170 | case TerminalState: | ||
171 | // Finished parsing. Push what should be the last | ||
172 | // statement to the stack. If there is anything left | ||
173 | // on the stack, an error in parsing has occurred. | ||
174 | if k.Kind != ASTKindStart { | ||
175 | stack.MarkComplete(k) | ||
176 | } | ||
177 | break loop | ||
178 | case SkipTokenState: | ||
179 | // When skipping a token, the previous state was popped off the stack. | ||
180 | // To maintain the correct state, the previous state will be pushed | ||
181 | // onto the stack. | ||
182 | stack.Push(k) | ||
183 | case StatementState: | ||
184 | if k.Kind != ASTKindStart { | ||
185 | stack.MarkComplete(k) | ||
186 | } | ||
187 | expr := newExpression(tok) | ||
188 | stack.Push(expr) | ||
189 | case StatementPrimeState: | ||
190 | if tok.Type() != TokenOp { | ||
191 | stack.MarkComplete(k) | ||
192 | continue | ||
193 | } | ||
194 | |||
195 | if k.Kind != ASTKindExpr { | ||
196 | return nil, NewParseError( | ||
197 | fmt.Sprintf("invalid expression: expected Expr type, but found %T type", k), | ||
198 | ) | ||
199 | } | ||
200 | |||
201 | k = trimSpaces(k) | ||
202 | expr := newEqualExpr(k, tok) | ||
203 | stack.Push(expr) | ||
204 | case ValueState: | ||
205 | // ValueState requires the previous state to either be an equal expression | ||
206 | // or an expression statement. | ||
207 | // | ||
208 | // This grammar occurs when the RHS is a number, word, or quoted string. | ||
209 | // equal_expr -> lit op equal_expr' | ||
210 | // equal_expr' -> number | string | quoted_string | ||
211 | // quoted_string -> " quoted_string' | ||
212 | // quoted_string' -> string quoted_string_end | ||
213 | // quoted_string_end -> " | ||
214 | // | ||
215 | // otherwise | ||
216 | // expr_stmt -> equal_expr (expr_stmt')* | ||
217 | // expr_stmt' -> ws S | op S | MarkComplete | ||
218 | // S -> equal_expr' expr_stmt' | ||
219 | switch k.Kind { | ||
220 | case ASTKindEqualExpr: | ||
221 | // assiging a value to some key | ||
222 | k.AppendChild(newExpression(tok)) | ||
223 | stack.Push(newExprStatement(k)) | ||
224 | case ASTKindExpr: | ||
225 | k.Root.raw = append(k.Root.raw, tok.Raw()...) | ||
226 | stack.Push(k) | ||
227 | case ASTKindExprStatement: | ||
228 | root := k.GetRoot() | ||
229 | children := root.GetChildren() | ||
230 | if len(children) == 0 { | ||
231 | return nil, NewParseError( | ||
232 | fmt.Sprintf("invalid expression: AST contains no children %s", k.Kind), | ||
233 | ) | ||
234 | } | ||
235 | |||
236 | rhs := children[len(children)-1] | ||
237 | |||
238 | if rhs.Root.ValueType != QuotedStringType { | ||
239 | rhs.Root.ValueType = StringType | ||
240 | rhs.Root.raw = append(rhs.Root.raw, tok.Raw()...) | ||
241 | |||
242 | } | ||
243 | |||
244 | children[len(children)-1] = rhs | ||
245 | k.SetChildren(children) | ||
246 | |||
247 | stack.Push(k) | ||
248 | } | ||
249 | case OpenScopeState: | ||
250 | if !runeCompare(tok.Raw(), openBrace) { | ||
251 | return nil, NewParseError("expected '['") | ||
252 | } | ||
253 | |||
254 | stmt := newStatement() | ||
255 | stack.Push(stmt) | ||
256 | case CloseScopeState: | ||
257 | if !runeCompare(tok.Raw(), closeBrace) { | ||
258 | return nil, NewParseError("expected ']'") | ||
259 | } | ||
260 | |||
261 | k = trimSpaces(k) | ||
262 | stack.Push(newCompletedSectionStatement(k)) | ||
263 | case SectionState: | ||
264 | var stmt AST | ||
265 | |||
266 | switch k.Kind { | ||
267 | case ASTKindStatement: | ||
268 | // If there are multiple literals inside of a scope declaration, | ||
269 | // then the current token's raw value will be appended to the Name. | ||
270 | // | ||
271 | // This handles cases like [ profile default ] | ||
272 | // | ||
273 | // k will represent a SectionStatement with the children representing | ||
274 | // the label of the section | ||
275 | stmt = newSectionStatement(tok) | ||
276 | case ASTKindSectionStatement: | ||
277 | k.Root.raw = append(k.Root.raw, tok.Raw()...) | ||
278 | stmt = k | ||
279 | default: | ||
280 | return nil, NewParseError( | ||
281 | fmt.Sprintf("invalid statement: expected statement: %v", k.Kind), | ||
282 | ) | ||
283 | } | ||
284 | |||
285 | stack.Push(stmt) | ||
286 | case MarkCompleteState: | ||
287 | if k.Kind != ASTKindStart { | ||
288 | stack.MarkComplete(k) | ||
289 | } | ||
290 | |||
291 | if stack.Len() == 0 { | ||
292 | stack.Push(start) | ||
293 | } | ||
294 | case SkipState: | ||
295 | stack.Push(newSkipStatement(k)) | ||
296 | s.Skip() | ||
297 | case CommentState: | ||
298 | if k.Kind == ASTKindStart { | ||
299 | stack.Push(k) | ||
300 | } else { | ||
301 | stack.MarkComplete(k) | ||
302 | } | ||
303 | |||
304 | stmt := newCommentStatement(tok) | ||
305 | stack.Push(stmt) | ||
306 | default: | ||
307 | return nil, NewParseError(fmt.Sprintf("invalid state with ASTKind %v and TokenType %v", k, tok)) | ||
308 | } | ||
309 | |||
310 | if len(tokens) > 0 { | ||
311 | tokens = tokens[1:] | ||
312 | } | ||
313 | } | ||
314 | |||
315 | // this occurs when a statement has not been completed | ||
316 | if stack.top > 1 { | ||
317 | return nil, NewParseError(fmt.Sprintf("incomplete expression: %v", stack.container)) | ||
318 | } | ||
319 | |||
320 | // returns a sublist which excludes the start symbol | ||
321 | return stack.List(), nil | ||
322 | } | ||
323 | |||
324 | // trimSpaces will trim spaces on the left and right hand side of | ||
325 | // the literal. | ||
326 | func trimSpaces(k AST) AST { | ||
327 | // trim left hand side of spaces | ||
328 | for i := 0; i < len(k.Root.raw); i++ { | ||
329 | if !isWhitespace(k.Root.raw[i]) { | ||
330 | break | ||
331 | } | ||
332 | |||
333 | k.Root.raw = k.Root.raw[1:] | ||
334 | i-- | ||
335 | } | ||
336 | |||
337 | // trim right hand side of spaces | ||
338 | for i := len(k.Root.raw) - 1; i >= 0; i-- { | ||
339 | if !isWhitespace(k.Root.raw[i]) { | ||
340 | break | ||
341 | } | ||
342 | |||
343 | k.Root.raw = k.Root.raw[:len(k.Root.raw)-1] | ||
344 | } | ||
345 | |||
346 | return k | ||
347 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/literal_tokens.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/literal_tokens.go new file mode 100644 index 0000000..24df543 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/literal_tokens.go | |||
@@ -0,0 +1,324 @@ | |||
1 | package ini | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "strconv" | ||
6 | "strings" | ||
7 | ) | ||
8 | |||
9 | var ( | ||
10 | runesTrue = []rune("true") | ||
11 | runesFalse = []rune("false") | ||
12 | ) | ||
13 | |||
14 | var literalValues = [][]rune{ | ||
15 | runesTrue, | ||
16 | runesFalse, | ||
17 | } | ||
18 | |||
19 | func isBoolValue(b []rune) bool { | ||
20 | for _, lv := range literalValues { | ||
21 | if isLitValue(lv, b) { | ||
22 | return true | ||
23 | } | ||
24 | } | ||
25 | return false | ||
26 | } | ||
27 | |||
28 | func isLitValue(want, have []rune) bool { | ||
29 | if len(have) < len(want) { | ||
30 | return false | ||
31 | } | ||
32 | |||
33 | for i := 0; i < len(want); i++ { | ||
34 | if want[i] != have[i] { | ||
35 | return false | ||
36 | } | ||
37 | } | ||
38 | |||
39 | return true | ||
40 | } | ||
41 | |||
42 | // isNumberValue will return whether not the leading characters in | ||
43 | // a byte slice is a number. A number is delimited by whitespace or | ||
44 | // the newline token. | ||
45 | // | ||
46 | // A number is defined to be in a binary, octal, decimal (int | float), hex format, | ||
47 | // or in scientific notation. | ||
48 | func isNumberValue(b []rune) bool { | ||
49 | negativeIndex := 0 | ||
50 | helper := numberHelper{} | ||
51 | needDigit := false | ||
52 | |||
53 | for i := 0; i < len(b); i++ { | ||
54 | negativeIndex++ | ||
55 | |||
56 | switch b[i] { | ||
57 | case '-': | ||
58 | if helper.IsNegative() || negativeIndex != 1 { | ||
59 | return false | ||
60 | } | ||
61 | helper.Determine(b[i]) | ||
62 | needDigit = true | ||
63 | continue | ||
64 | case 'e', 'E': | ||
65 | if err := helper.Determine(b[i]); err != nil { | ||
66 | return false | ||
67 | } | ||
68 | negativeIndex = 0 | ||
69 | needDigit = true | ||
70 | continue | ||
71 | case 'b': | ||
72 | if helper.numberFormat == hex { | ||
73 | break | ||
74 | } | ||
75 | fallthrough | ||
76 | case 'o', 'x': | ||
77 | needDigit = true | ||
78 | if i == 0 { | ||
79 | return false | ||
80 | } | ||
81 | |||
82 | fallthrough | ||
83 | case '.': | ||
84 | if err := helper.Determine(b[i]); err != nil { | ||
85 | return false | ||
86 | } | ||
87 | needDigit = true | ||
88 | continue | ||
89 | } | ||
90 | |||
91 | if i > 0 && (isNewline(b[i:]) || isWhitespace(b[i])) { | ||
92 | return !needDigit | ||
93 | } | ||
94 | |||
95 | if !helper.CorrectByte(b[i]) { | ||
96 | return false | ||
97 | } | ||
98 | needDigit = false | ||
99 | } | ||
100 | |||
101 | return !needDigit | ||
102 | } | ||
103 | |||
104 | func isValid(b []rune) (bool, int, error) { | ||
105 | if len(b) == 0 { | ||
106 | // TODO: should probably return an error | ||
107 | return false, 0, nil | ||
108 | } | ||
109 | |||
110 | return isValidRune(b[0]), 1, nil | ||
111 | } | ||
112 | |||
113 | func isValidRune(r rune) bool { | ||
114 | return r != ':' && r != '=' && r != '[' && r != ']' && r != ' ' && r != '\n' | ||
115 | } | ||
116 | |||
117 | // ValueType is an enum that will signify what type | ||
118 | // the Value is | ||
119 | type ValueType int | ||
120 | |||
121 | func (v ValueType) String() string { | ||
122 | switch v { | ||
123 | case NoneType: | ||
124 | return "NONE" | ||
125 | case DecimalType: | ||
126 | return "FLOAT" | ||
127 | case IntegerType: | ||
128 | return "INT" | ||
129 | case StringType: | ||
130 | return "STRING" | ||
131 | case BoolType: | ||
132 | return "BOOL" | ||
133 | } | ||
134 | |||
135 | return "" | ||
136 | } | ||
137 | |||
138 | // ValueType enums | ||
139 | const ( | ||
140 | NoneType = ValueType(iota) | ||
141 | DecimalType | ||
142 | IntegerType | ||
143 | StringType | ||
144 | QuotedStringType | ||
145 | BoolType | ||
146 | ) | ||
147 | |||
148 | // Value is a union container | ||
149 | type Value struct { | ||
150 | Type ValueType | ||
151 | raw []rune | ||
152 | |||
153 | integer int64 | ||
154 | decimal float64 | ||
155 | boolean bool | ||
156 | str string | ||
157 | } | ||
158 | |||
159 | func newValue(t ValueType, base int, raw []rune) (Value, error) { | ||
160 | v := Value{ | ||
161 | Type: t, | ||
162 | raw: raw, | ||
163 | } | ||
164 | var err error | ||
165 | |||
166 | switch t { | ||
167 | case DecimalType: | ||
168 | v.decimal, err = strconv.ParseFloat(string(raw), 64) | ||
169 | case IntegerType: | ||
170 | if base != 10 { | ||
171 | raw = raw[2:] | ||
172 | } | ||
173 | |||
174 | v.integer, err = strconv.ParseInt(string(raw), base, 64) | ||
175 | case StringType: | ||
176 | v.str = string(raw) | ||
177 | case QuotedStringType: | ||
178 | v.str = string(raw[1 : len(raw)-1]) | ||
179 | case BoolType: | ||
180 | v.boolean = runeCompare(v.raw, runesTrue) | ||
181 | } | ||
182 | |||
183 | // issue 2253 | ||
184 | // | ||
185 | // if the value trying to be parsed is too large, then we will use | ||
186 | // the 'StringType' and raw value instead. | ||
187 | if nerr, ok := err.(*strconv.NumError); ok && nerr.Err == strconv.ErrRange { | ||
188 | v.Type = StringType | ||
189 | v.str = string(raw) | ||
190 | err = nil | ||
191 | } | ||
192 | |||
193 | return v, err | ||
194 | } | ||
195 | |||
196 | // Append will append values and change the type to a string | ||
197 | // type. | ||
198 | func (v *Value) Append(tok Token) { | ||
199 | r := tok.Raw() | ||
200 | if v.Type != QuotedStringType { | ||
201 | v.Type = StringType | ||
202 | r = tok.raw[1 : len(tok.raw)-1] | ||
203 | } | ||
204 | if tok.Type() != TokenLit { | ||
205 | v.raw = append(v.raw, tok.Raw()...) | ||
206 | } else { | ||
207 | v.raw = append(v.raw, r...) | ||
208 | } | ||
209 | } | ||
210 | |||
211 | func (v Value) String() string { | ||
212 | switch v.Type { | ||
213 | case DecimalType: | ||
214 | return fmt.Sprintf("decimal: %f", v.decimal) | ||
215 | case IntegerType: | ||
216 | return fmt.Sprintf("integer: %d", v.integer) | ||
217 | case StringType: | ||
218 | return fmt.Sprintf("string: %s", string(v.raw)) | ||
219 | case QuotedStringType: | ||
220 | return fmt.Sprintf("quoted string: %s", string(v.raw)) | ||
221 | case BoolType: | ||
222 | return fmt.Sprintf("bool: %t", v.boolean) | ||
223 | default: | ||
224 | return "union not set" | ||
225 | } | ||
226 | } | ||
227 | |||
228 | func newLitToken(b []rune) (Token, int, error) { | ||
229 | n := 0 | ||
230 | var err error | ||
231 | |||
232 | token := Token{} | ||
233 | if b[0] == '"' { | ||
234 | n, err = getStringValue(b) | ||
235 | if err != nil { | ||
236 | return token, n, err | ||
237 | } | ||
238 | |||
239 | token = newToken(TokenLit, b[:n], QuotedStringType) | ||
240 | } else if isNumberValue(b) { | ||
241 | var base int | ||
242 | base, n, err = getNumericalValue(b) | ||
243 | if err != nil { | ||
244 | return token, 0, err | ||
245 | } | ||
246 | |||
247 | value := b[:n] | ||
248 | vType := IntegerType | ||
249 | if contains(value, '.') || hasExponent(value) { | ||
250 | vType = DecimalType | ||
251 | } | ||
252 | token = newToken(TokenLit, value, vType) | ||
253 | token.base = base | ||
254 | } else if isBoolValue(b) { | ||
255 | n, err = getBoolValue(b) | ||
256 | |||
257 | token = newToken(TokenLit, b[:n], BoolType) | ||
258 | } else { | ||
259 | n, err = getValue(b) | ||
260 | token = newToken(TokenLit, b[:n], StringType) | ||
261 | } | ||
262 | |||
263 | return token, n, err | ||
264 | } | ||
265 | |||
266 | // IntValue returns an integer value | ||
267 | func (v Value) IntValue() int64 { | ||
268 | return v.integer | ||
269 | } | ||
270 | |||
271 | // FloatValue returns a float value | ||
272 | func (v Value) FloatValue() float64 { | ||
273 | return v.decimal | ||
274 | } | ||
275 | |||
276 | // BoolValue returns a bool value | ||
277 | func (v Value) BoolValue() bool { | ||
278 | return v.boolean | ||
279 | } | ||
280 | |||
281 | func isTrimmable(r rune) bool { | ||
282 | switch r { | ||
283 | case '\n', ' ': | ||
284 | return true | ||
285 | } | ||
286 | return false | ||
287 | } | ||
288 | |||
289 | // StringValue returns the string value | ||
290 | func (v Value) StringValue() string { | ||
291 | switch v.Type { | ||
292 | case StringType: | ||
293 | return strings.TrimFunc(string(v.raw), isTrimmable) | ||
294 | case QuotedStringType: | ||
295 | // preserve all characters in the quotes | ||
296 | return string(removeEscapedCharacters(v.raw[1 : len(v.raw)-1])) | ||
297 | default: | ||
298 | return strings.TrimFunc(string(v.raw), isTrimmable) | ||
299 | } | ||
300 | } | ||
301 | |||
302 | func contains(runes []rune, c rune) bool { | ||
303 | for i := 0; i < len(runes); i++ { | ||
304 | if runes[i] == c { | ||
305 | return true | ||
306 | } | ||
307 | } | ||
308 | |||
309 | return false | ||
310 | } | ||
311 | |||
312 | func runeCompare(v1 []rune, v2 []rune) bool { | ||
313 | if len(v1) != len(v2) { | ||
314 | return false | ||
315 | } | ||
316 | |||
317 | for i := 0; i < len(v1); i++ { | ||
318 | if v1[i] != v2[i] { | ||
319 | return false | ||
320 | } | ||
321 | } | ||
322 | |||
323 | return true | ||
324 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/newline_token.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/newline_token.go new file mode 100644 index 0000000..e52ac39 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/newline_token.go | |||
@@ -0,0 +1,30 @@ | |||
1 | package ini | ||
2 | |||
3 | func isNewline(b []rune) bool { | ||
4 | if len(b) == 0 { | ||
5 | return false | ||
6 | } | ||
7 | |||
8 | if b[0] == '\n' { | ||
9 | return true | ||
10 | } | ||
11 | |||
12 | if len(b) < 2 { | ||
13 | return false | ||
14 | } | ||
15 | |||
16 | return b[0] == '\r' && b[1] == '\n' | ||
17 | } | ||
18 | |||
19 | func newNewlineToken(b []rune) (Token, int, error) { | ||
20 | i := 1 | ||
21 | if b[0] == '\r' && isNewline(b[1:]) { | ||
22 | i++ | ||
23 | } | ||
24 | |||
25 | if !isNewline([]rune(b[:i])) { | ||
26 | return emptyToken, 0, NewParseError("invalid new line token") | ||
27 | } | ||
28 | |||
29 | return newToken(TokenNL, b[:i], NoneType), i, nil | ||
30 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/number_helper.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/number_helper.go new file mode 100644 index 0000000..a45c0bc --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/number_helper.go | |||
@@ -0,0 +1,152 @@ | |||
1 | package ini | ||
2 | |||
3 | import ( | ||
4 | "bytes" | ||
5 | "fmt" | ||
6 | "strconv" | ||
7 | ) | ||
8 | |||
9 | const ( | ||
10 | none = numberFormat(iota) | ||
11 | binary | ||
12 | octal | ||
13 | decimal | ||
14 | hex | ||
15 | exponent | ||
16 | ) | ||
17 | |||
18 | type numberFormat int | ||
19 | |||
20 | // numberHelper is used to dictate what format a number is in | ||
21 | // and what to do for negative values. Since -1e-4 is a valid | ||
22 | // number, we cannot just simply check for duplicate negatives. | ||
23 | type numberHelper struct { | ||
24 | numberFormat numberFormat | ||
25 | |||
26 | negative bool | ||
27 | negativeExponent bool | ||
28 | } | ||
29 | |||
30 | func (b numberHelper) Exists() bool { | ||
31 | return b.numberFormat != none | ||
32 | } | ||
33 | |||
34 | func (b numberHelper) IsNegative() bool { | ||
35 | return b.negative || b.negativeExponent | ||
36 | } | ||
37 | |||
38 | func (b *numberHelper) Determine(c rune) error { | ||
39 | if b.Exists() { | ||
40 | return NewParseError(fmt.Sprintf("multiple number formats: 0%v", string(c))) | ||
41 | } | ||
42 | |||
43 | switch c { | ||
44 | case 'b': | ||
45 | b.numberFormat = binary | ||
46 | case 'o': | ||
47 | b.numberFormat = octal | ||
48 | case 'x': | ||
49 | b.numberFormat = hex | ||
50 | case 'e', 'E': | ||
51 | b.numberFormat = exponent | ||
52 | case '-': | ||
53 | if b.numberFormat != exponent { | ||
54 | b.negative = true | ||
55 | } else { | ||
56 | b.negativeExponent = true | ||
57 | } | ||
58 | case '.': | ||
59 | b.numberFormat = decimal | ||
60 | default: | ||
61 | return NewParseError(fmt.Sprintf("invalid number character: %v", string(c))) | ||
62 | } | ||
63 | |||
64 | return nil | ||
65 | } | ||
66 | |||
67 | func (b numberHelper) CorrectByte(c rune) bool { | ||
68 | switch { | ||
69 | case b.numberFormat == binary: | ||
70 | if !isBinaryByte(c) { | ||
71 | return false | ||
72 | } | ||
73 | case b.numberFormat == octal: | ||
74 | if !isOctalByte(c) { | ||
75 | return false | ||
76 | } | ||
77 | case b.numberFormat == hex: | ||
78 | if !isHexByte(c) { | ||
79 | return false | ||
80 | } | ||
81 | case b.numberFormat == decimal: | ||
82 | if !isDigit(c) { | ||
83 | return false | ||
84 | } | ||
85 | case b.numberFormat == exponent: | ||
86 | if !isDigit(c) { | ||
87 | return false | ||
88 | } | ||
89 | case b.negativeExponent: | ||
90 | if !isDigit(c) { | ||
91 | return false | ||
92 | } | ||
93 | case b.negative: | ||
94 | if !isDigit(c) { | ||
95 | return false | ||
96 | } | ||
97 | default: | ||
98 | if !isDigit(c) { | ||
99 | return false | ||
100 | } | ||
101 | } | ||
102 | |||
103 | return true | ||
104 | } | ||
105 | |||
106 | func (b numberHelper) Base() int { | ||
107 | switch b.numberFormat { | ||
108 | case binary: | ||
109 | return 2 | ||
110 | case octal: | ||
111 | return 8 | ||
112 | case hex: | ||
113 | return 16 | ||
114 | default: | ||
115 | return 10 | ||
116 | } | ||
117 | } | ||
118 | |||
119 | func (b numberHelper) String() string { | ||
120 | buf := bytes.Buffer{} | ||
121 | i := 0 | ||
122 | |||
123 | switch b.numberFormat { | ||
124 | case binary: | ||
125 | i++ | ||
126 | buf.WriteString(strconv.Itoa(i) + ": binary format\n") | ||
127 | case octal: | ||
128 | i++ | ||
129 | buf.WriteString(strconv.Itoa(i) + ": octal format\n") | ||
130 | case hex: | ||
131 | i++ | ||
132 | buf.WriteString(strconv.Itoa(i) + ": hex format\n") | ||
133 | case exponent: | ||
134 | i++ | ||
135 | buf.WriteString(strconv.Itoa(i) + ": exponent format\n") | ||
136 | default: | ||
137 | i++ | ||
138 | buf.WriteString(strconv.Itoa(i) + ": integer format\n") | ||
139 | } | ||
140 | |||
141 | if b.negative { | ||
142 | i++ | ||
143 | buf.WriteString(strconv.Itoa(i) + ": negative format\n") | ||
144 | } | ||
145 | |||
146 | if b.negativeExponent { | ||
147 | i++ | ||
148 | buf.WriteString(strconv.Itoa(i) + ": negative exponent format\n") | ||
149 | } | ||
150 | |||
151 | return buf.String() | ||
152 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/op_tokens.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/op_tokens.go new file mode 100644 index 0000000..8a84c7c --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/op_tokens.go | |||
@@ -0,0 +1,39 @@ | |||
1 | package ini | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | ) | ||
6 | |||
7 | var ( | ||
8 | equalOp = []rune("=") | ||
9 | equalColonOp = []rune(":") | ||
10 | ) | ||
11 | |||
12 | func isOp(b []rune) bool { | ||
13 | if len(b) == 0 { | ||
14 | return false | ||
15 | } | ||
16 | |||
17 | switch b[0] { | ||
18 | case '=': | ||
19 | return true | ||
20 | case ':': | ||
21 | return true | ||
22 | default: | ||
23 | return false | ||
24 | } | ||
25 | } | ||
26 | |||
27 | func newOpToken(b []rune) (Token, int, error) { | ||
28 | tok := Token{} | ||
29 | |||
30 | switch b[0] { | ||
31 | case '=': | ||
32 | tok = newToken(TokenOp, equalOp, NoneType) | ||
33 | case ':': | ||
34 | tok = newToken(TokenOp, equalColonOp, NoneType) | ||
35 | default: | ||
36 | return tok, 0, NewParseError(fmt.Sprintf("unexpected op type, %v", b[0])) | ||
37 | } | ||
38 | return tok, 1, nil | ||
39 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/parse_error.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/parse_error.go new file mode 100644 index 0000000..4572870 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/parse_error.go | |||
@@ -0,0 +1,43 @@ | |||
1 | package ini | ||
2 | |||
3 | import "fmt" | ||
4 | |||
5 | const ( | ||
6 | // ErrCodeParseError is returned when a parsing error | ||
7 | // has occurred. | ||
8 | ErrCodeParseError = "INIParseError" | ||
9 | ) | ||
10 | |||
11 | // ParseError is an error which is returned during any part of | ||
12 | // the parsing process. | ||
13 | type ParseError struct { | ||
14 | msg string | ||
15 | } | ||
16 | |||
17 | // NewParseError will return a new ParseError where message | ||
18 | // is the description of the error. | ||
19 | func NewParseError(message string) *ParseError { | ||
20 | return &ParseError{ | ||
21 | msg: message, | ||
22 | } | ||
23 | } | ||
24 | |||
25 | // Code will return the ErrCodeParseError | ||
26 | func (err *ParseError) Code() string { | ||
27 | return ErrCodeParseError | ||
28 | } | ||
29 | |||
30 | // Message returns the error's message | ||
31 | func (err *ParseError) Message() string { | ||
32 | return err.msg | ||
33 | } | ||
34 | |||
35 | // OrigError return nothing since there will never be any | ||
36 | // original error. | ||
37 | func (err *ParseError) OrigError() error { | ||
38 | return nil | ||
39 | } | ||
40 | |||
41 | func (err *ParseError) Error() string { | ||
42 | return fmt.Sprintf("%s: %s", err.Code(), err.Message()) | ||
43 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/parse_stack.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/parse_stack.go new file mode 100644 index 0000000..7f01cf7 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/parse_stack.go | |||
@@ -0,0 +1,60 @@ | |||
1 | package ini | ||
2 | |||
3 | import ( | ||
4 | "bytes" | ||
5 | "fmt" | ||
6 | ) | ||
7 | |||
8 | // ParseStack is a stack that contains a container, the stack portion, | ||
9 | // and the list which is the list of ASTs that have been successfully | ||
10 | // parsed. | ||
11 | type ParseStack struct { | ||
12 | top int | ||
13 | container []AST | ||
14 | list []AST | ||
15 | index int | ||
16 | } | ||
17 | |||
18 | func newParseStack(sizeContainer, sizeList int) ParseStack { | ||
19 | return ParseStack{ | ||
20 | container: make([]AST, sizeContainer), | ||
21 | list: make([]AST, sizeList), | ||
22 | } | ||
23 | } | ||
24 | |||
25 | // Pop will return and truncate the last container element. | ||
26 | func (s *ParseStack) Pop() AST { | ||
27 | s.top-- | ||
28 | return s.container[s.top] | ||
29 | } | ||
30 | |||
31 | // Push will add the new AST to the container | ||
32 | func (s *ParseStack) Push(ast AST) { | ||
33 | s.container[s.top] = ast | ||
34 | s.top++ | ||
35 | } | ||
36 | |||
37 | // MarkComplete will append the AST to the list of completed statements | ||
38 | func (s *ParseStack) MarkComplete(ast AST) { | ||
39 | s.list[s.index] = ast | ||
40 | s.index++ | ||
41 | } | ||
42 | |||
43 | // List will return the completed statements | ||
44 | func (s ParseStack) List() []AST { | ||
45 | return s.list[:s.index] | ||
46 | } | ||
47 | |||
48 | // Len will return the length of the container | ||
49 | func (s *ParseStack) Len() int { | ||
50 | return s.top | ||
51 | } | ||
52 | |||
53 | func (s ParseStack) String() string { | ||
54 | buf := bytes.Buffer{} | ||
55 | for i, node := range s.list { | ||
56 | buf.WriteString(fmt.Sprintf("%d: %v\n", i+1, node)) | ||
57 | } | ||
58 | |||
59 | return buf.String() | ||
60 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/sep_tokens.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/sep_tokens.go new file mode 100644 index 0000000..f82095b --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/sep_tokens.go | |||
@@ -0,0 +1,41 @@ | |||
1 | package ini | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | ) | ||
6 | |||
7 | var ( | ||
8 | emptyRunes = []rune{} | ||
9 | ) | ||
10 | |||
11 | func isSep(b []rune) bool { | ||
12 | if len(b) == 0 { | ||
13 | return false | ||
14 | } | ||
15 | |||
16 | switch b[0] { | ||
17 | case '[', ']': | ||
18 | return true | ||
19 | default: | ||
20 | return false | ||
21 | } | ||
22 | } | ||
23 | |||
24 | var ( | ||
25 | openBrace = []rune("[") | ||
26 | closeBrace = []rune("]") | ||
27 | ) | ||
28 | |||
29 | func newSepToken(b []rune) (Token, int, error) { | ||
30 | tok := Token{} | ||
31 | |||
32 | switch b[0] { | ||
33 | case '[': | ||
34 | tok = newToken(TokenSep, openBrace, NoneType) | ||
35 | case ']': | ||
36 | tok = newToken(TokenSep, closeBrace, NoneType) | ||
37 | default: | ||
38 | return tok, 0, NewParseError(fmt.Sprintf("unexpected sep type, %v", b[0])) | ||
39 | } | ||
40 | return tok, 1, nil | ||
41 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/skipper.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/skipper.go new file mode 100644 index 0000000..6bb6964 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/skipper.go | |||
@@ -0,0 +1,45 @@ | |||
1 | package ini | ||
2 | |||
3 | // skipper is used to skip certain blocks of an ini file. | ||
4 | // Currently skipper is used to skip nested blocks of ini | ||
5 | // files. See example below | ||
6 | // | ||
7 | // [ foo ] | ||
8 | // nested = ; this section will be skipped | ||
9 | // a=b | ||
10 | // c=d | ||
11 | // bar=baz ; this will be included | ||
12 | type skipper struct { | ||
13 | shouldSkip bool | ||
14 | TokenSet bool | ||
15 | prevTok Token | ||
16 | } | ||
17 | |||
18 | func newSkipper() skipper { | ||
19 | return skipper{ | ||
20 | prevTok: emptyToken, | ||
21 | } | ||
22 | } | ||
23 | |||
24 | func (s *skipper) ShouldSkip(tok Token) bool { | ||
25 | if s.shouldSkip && | ||
26 | s.prevTok.Type() == TokenNL && | ||
27 | tok.Type() != TokenWS { | ||
28 | |||
29 | s.Continue() | ||
30 | return false | ||
31 | } | ||
32 | s.prevTok = tok | ||
33 | |||
34 | return s.shouldSkip | ||
35 | } | ||
36 | |||
37 | func (s *skipper) Skip() { | ||
38 | s.shouldSkip = true | ||
39 | s.prevTok = emptyToken | ||
40 | } | ||
41 | |||
42 | func (s *skipper) Continue() { | ||
43 | s.shouldSkip = false | ||
44 | s.prevTok = emptyToken | ||
45 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/statement.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/statement.go new file mode 100644 index 0000000..18f3fe8 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/statement.go | |||
@@ -0,0 +1,35 @@ | |||
1 | package ini | ||
2 | |||
3 | // Statement is an empty AST mostly used for transitioning states. | ||
4 | func newStatement() AST { | ||
5 | return newAST(ASTKindStatement, AST{}) | ||
6 | } | ||
7 | |||
8 | // SectionStatement represents a section AST | ||
9 | func newSectionStatement(tok Token) AST { | ||
10 | return newASTWithRootToken(ASTKindSectionStatement, tok) | ||
11 | } | ||
12 | |||
13 | // ExprStatement represents a completed expression AST | ||
14 | func newExprStatement(ast AST) AST { | ||
15 | return newAST(ASTKindExprStatement, ast) | ||
16 | } | ||
17 | |||
18 | // CommentStatement represents a comment in the ini definition. | ||
19 | // | ||
20 | // grammar: | ||
21 | // comment -> #comment' | ;comment' | ||
22 | // comment' -> epsilon | value | ||
23 | func newCommentStatement(tok Token) AST { | ||
24 | return newAST(ASTKindCommentStatement, newExpression(tok)) | ||
25 | } | ||
26 | |||
27 | // CompletedSectionStatement represents a completed section | ||
28 | func newCompletedSectionStatement(ast AST) AST { | ||
29 | return newAST(ASTKindCompletedSectionStatement, ast) | ||
30 | } | ||
31 | |||
32 | // SkipStatement is used to skip whole statements | ||
33 | func newSkipStatement(ast AST) AST { | ||
34 | return newAST(ASTKindSkipStatement, ast) | ||
35 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/value_util.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/value_util.go new file mode 100644 index 0000000..305999d --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/value_util.go | |||
@@ -0,0 +1,284 @@ | |||
1 | package ini | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | ) | ||
6 | |||
7 | // getStringValue will return a quoted string and the amount | ||
8 | // of bytes read | ||
9 | // | ||
10 | // an error will be returned if the string is not properly formatted | ||
11 | func getStringValue(b []rune) (int, error) { | ||
12 | if b[0] != '"' { | ||
13 | return 0, NewParseError("strings must start with '\"'") | ||
14 | } | ||
15 | |||
16 | endQuote := false | ||
17 | i := 1 | ||
18 | |||
19 | for ; i < len(b) && !endQuote; i++ { | ||
20 | if escaped := isEscaped(b[:i], b[i]); b[i] == '"' && !escaped { | ||
21 | endQuote = true | ||
22 | break | ||
23 | } else if escaped { | ||
24 | /*c, err := getEscapedByte(b[i]) | ||
25 | if err != nil { | ||
26 | return 0, err | ||
27 | } | ||
28 | |||
29 | b[i-1] = c | ||
30 | b = append(b[:i], b[i+1:]...) | ||
31 | i--*/ | ||
32 | |||
33 | continue | ||
34 | } | ||
35 | } | ||
36 | |||
37 | if !endQuote { | ||
38 | return 0, NewParseError("missing '\"' in string value") | ||
39 | } | ||
40 | |||
41 | return i + 1, nil | ||
42 | } | ||
43 | |||
44 | // getBoolValue will return a boolean and the amount | ||
45 | // of bytes read | ||
46 | // | ||
47 | // an error will be returned if the boolean is not of a correct | ||
48 | // value | ||
49 | func getBoolValue(b []rune) (int, error) { | ||
50 | if len(b) < 4 { | ||
51 | return 0, NewParseError("invalid boolean value") | ||
52 | } | ||
53 | |||
54 | n := 0 | ||
55 | for _, lv := range literalValues { | ||
56 | if len(lv) > len(b) { | ||
57 | continue | ||
58 | } | ||
59 | |||
60 | if isLitValue(lv, b) { | ||
61 | n = len(lv) | ||
62 | } | ||
63 | } | ||
64 | |||
65 | if n == 0 { | ||
66 | return 0, NewParseError("invalid boolean value") | ||
67 | } | ||
68 | |||
69 | return n, nil | ||
70 | } | ||
71 | |||
72 | // getNumericalValue will return a numerical string, the amount | ||
73 | // of bytes read, and the base of the number | ||
74 | // | ||
75 | // an error will be returned if the number is not of a correct | ||
76 | // value | ||
77 | func getNumericalValue(b []rune) (int, int, error) { | ||
78 | if !isDigit(b[0]) { | ||
79 | return 0, 0, NewParseError("invalid digit value") | ||
80 | } | ||
81 | |||
82 | i := 0 | ||
83 | helper := numberHelper{} | ||
84 | |||
85 | loop: | ||
86 | for negativeIndex := 0; i < len(b); i++ { | ||
87 | negativeIndex++ | ||
88 | |||
89 | if !isDigit(b[i]) { | ||
90 | switch b[i] { | ||
91 | case '-': | ||
92 | if helper.IsNegative() || negativeIndex != 1 { | ||
93 | return 0, 0, NewParseError("parse error '-'") | ||
94 | } | ||
95 | |||
96 | n := getNegativeNumber(b[i:]) | ||
97 | i += (n - 1) | ||
98 | helper.Determine(b[i]) | ||
99 | continue | ||
100 | case '.': | ||
101 | if err := helper.Determine(b[i]); err != nil { | ||
102 | return 0, 0, err | ||
103 | } | ||
104 | case 'e', 'E': | ||
105 | if err := helper.Determine(b[i]); err != nil { | ||
106 | return 0, 0, err | ||
107 | } | ||
108 | |||
109 | negativeIndex = 0 | ||
110 | case 'b': | ||
111 | if helper.numberFormat == hex { | ||
112 | break | ||
113 | } | ||
114 | fallthrough | ||
115 | case 'o', 'x': | ||
116 | if i == 0 && b[i] != '0' { | ||
117 | return 0, 0, NewParseError("incorrect base format, expected leading '0'") | ||
118 | } | ||
119 | |||
120 | if i != 1 { | ||
121 | return 0, 0, NewParseError(fmt.Sprintf("incorrect base format found %s at %d index", string(b[i]), i)) | ||
122 | } | ||
123 | |||
124 | if err := helper.Determine(b[i]); err != nil { | ||
125 | return 0, 0, err | ||
126 | } | ||
127 | default: | ||
128 | if isWhitespace(b[i]) { | ||
129 | break loop | ||
130 | } | ||
131 | |||
132 | if isNewline(b[i:]) { | ||
133 | break loop | ||
134 | } | ||
135 | |||
136 | if !(helper.numberFormat == hex && isHexByte(b[i])) { | ||
137 | if i+2 < len(b) && !isNewline(b[i:i+2]) { | ||
138 | return 0, 0, NewParseError("invalid numerical character") | ||
139 | } else if !isNewline([]rune{b[i]}) { | ||
140 | return 0, 0, NewParseError("invalid numerical character") | ||
141 | } | ||
142 | |||
143 | break loop | ||
144 | } | ||
145 | } | ||
146 | } | ||
147 | } | ||
148 | |||
149 | return helper.Base(), i, nil | ||
150 | } | ||
151 | |||
152 | // isDigit will return whether or not something is an integer | ||
153 | func isDigit(b rune) bool { | ||
154 | return b >= '0' && b <= '9' | ||
155 | } | ||
156 | |||
157 | func hasExponent(v []rune) bool { | ||
158 | return contains(v, 'e') || contains(v, 'E') | ||
159 | } | ||
160 | |||
161 | func isBinaryByte(b rune) bool { | ||
162 | switch b { | ||
163 | case '0', '1': | ||
164 | return true | ||
165 | default: | ||
166 | return false | ||
167 | } | ||
168 | } | ||
169 | |||
170 | func isOctalByte(b rune) bool { | ||
171 | switch b { | ||
172 | case '0', '1', '2', '3', '4', '5', '6', '7': | ||
173 | return true | ||
174 | default: | ||
175 | return false | ||
176 | } | ||
177 | } | ||
178 | |||
179 | func isHexByte(b rune) bool { | ||
180 | if isDigit(b) { | ||
181 | return true | ||
182 | } | ||
183 | return (b >= 'A' && b <= 'F') || | ||
184 | (b >= 'a' && b <= 'f') | ||
185 | } | ||
186 | |||
187 | func getValue(b []rune) (int, error) { | ||
188 | i := 0 | ||
189 | |||
190 | for i < len(b) { | ||
191 | if isNewline(b[i:]) { | ||
192 | break | ||
193 | } | ||
194 | |||
195 | if isOp(b[i:]) { | ||
196 | break | ||
197 | } | ||
198 | |||
199 | valid, n, err := isValid(b[i:]) | ||
200 | if err != nil { | ||
201 | return 0, err | ||
202 | } | ||
203 | |||
204 | if !valid { | ||
205 | break | ||
206 | } | ||
207 | |||
208 | i += n | ||
209 | } | ||
210 | |||
211 | return i, nil | ||
212 | } | ||
213 | |||
214 | // getNegativeNumber will return a negative number from a | ||
215 | // byte slice. This will iterate through all characters until | ||
216 | // a non-digit has been found. | ||
217 | func getNegativeNumber(b []rune) int { | ||
218 | if b[0] != '-' { | ||
219 | return 0 | ||
220 | } | ||
221 | |||
222 | i := 1 | ||
223 | for ; i < len(b); i++ { | ||
224 | if !isDigit(b[i]) { | ||
225 | return i | ||
226 | } | ||
227 | } | ||
228 | |||
229 | return i | ||
230 | } | ||
231 | |||
232 | // isEscaped will return whether or not the character is an escaped | ||
233 | // character. | ||
234 | func isEscaped(value []rune, b rune) bool { | ||
235 | if len(value) == 0 { | ||
236 | return false | ||
237 | } | ||
238 | |||
239 | switch b { | ||
240 | case '\'': // single quote | ||
241 | case '"': // quote | ||
242 | case 'n': // newline | ||
243 | case 't': // tab | ||
244 | case '\\': // backslash | ||
245 | default: | ||
246 | return false | ||
247 | } | ||
248 | |||
249 | return value[len(value)-1] == '\\' | ||
250 | } | ||
251 | |||
252 | func getEscapedByte(b rune) (rune, error) { | ||
253 | switch b { | ||
254 | case '\'': // single quote | ||
255 | return '\'', nil | ||
256 | case '"': // quote | ||
257 | return '"', nil | ||
258 | case 'n': // newline | ||
259 | return '\n', nil | ||
260 | case 't': // table | ||
261 | return '\t', nil | ||
262 | case '\\': // backslash | ||
263 | return '\\', nil | ||
264 | default: | ||
265 | return b, NewParseError(fmt.Sprintf("invalid escaped character %c", b)) | ||
266 | } | ||
267 | } | ||
268 | |||
269 | func removeEscapedCharacters(b []rune) []rune { | ||
270 | for i := 0; i < len(b); i++ { | ||
271 | if isEscaped(b[:i], b[i]) { | ||
272 | c, err := getEscapedByte(b[i]) | ||
273 | if err != nil { | ||
274 | return b | ||
275 | } | ||
276 | |||
277 | b[i-1] = c | ||
278 | b = append(b[:i], b[i+1:]...) | ||
279 | i-- | ||
280 | } | ||
281 | } | ||
282 | |||
283 | return b | ||
284 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/visitor.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/visitor.go new file mode 100644 index 0000000..94841c3 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/visitor.go | |||
@@ -0,0 +1,166 @@ | |||
1 | package ini | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "sort" | ||
6 | ) | ||
7 | |||
8 | // Visitor is an interface used by walkers that will | ||
9 | // traverse an array of ASTs. | ||
10 | type Visitor interface { | ||
11 | VisitExpr(AST) error | ||
12 | VisitStatement(AST) error | ||
13 | } | ||
14 | |||
15 | // DefaultVisitor is used to visit statements and expressions | ||
16 | // and ensure that they are both of the correct format. | ||
17 | // In addition, upon visiting this will build sections and populate | ||
18 | // the Sections field which can be used to retrieve profile | ||
19 | // configuration. | ||
20 | type DefaultVisitor struct { | ||
21 | scope string | ||
22 | Sections Sections | ||
23 | } | ||
24 | |||
25 | // NewDefaultVisitor return a DefaultVisitor | ||
26 | func NewDefaultVisitor() *DefaultVisitor { | ||
27 | return &DefaultVisitor{ | ||
28 | Sections: Sections{ | ||
29 | container: map[string]Section{}, | ||
30 | }, | ||
31 | } | ||
32 | } | ||
33 | |||
34 | // VisitExpr visits expressions... | ||
35 | func (v *DefaultVisitor) VisitExpr(expr AST) error { | ||
36 | t := v.Sections.container[v.scope] | ||
37 | if t.values == nil { | ||
38 | t.values = values{} | ||
39 | } | ||
40 | |||
41 | switch expr.Kind { | ||
42 | case ASTKindExprStatement: | ||
43 | opExpr := expr.GetRoot() | ||
44 | switch opExpr.Kind { | ||
45 | case ASTKindEqualExpr: | ||
46 | children := opExpr.GetChildren() | ||
47 | if len(children) <= 1 { | ||
48 | return NewParseError("unexpected token type") | ||
49 | } | ||
50 | |||
51 | rhs := children[1] | ||
52 | |||
53 | if rhs.Root.Type() != TokenLit { | ||
54 | return NewParseError("unexpected token type") | ||
55 | } | ||
56 | |||
57 | key := EqualExprKey(opExpr) | ||
58 | v, err := newValue(rhs.Root.ValueType, rhs.Root.base, rhs.Root.Raw()) | ||
59 | if err != nil { | ||
60 | return err | ||
61 | } | ||
62 | |||
63 | t.values[key] = v | ||
64 | default: | ||
65 | return NewParseError(fmt.Sprintf("unsupported expression %v", expr)) | ||
66 | } | ||
67 | default: | ||
68 | return NewParseError(fmt.Sprintf("unsupported expression %v", expr)) | ||
69 | } | ||
70 | |||
71 | v.Sections.container[v.scope] = t | ||
72 | return nil | ||
73 | } | ||
74 | |||
75 | // VisitStatement visits statements... | ||
76 | func (v *DefaultVisitor) VisitStatement(stmt AST) error { | ||
77 | switch stmt.Kind { | ||
78 | case ASTKindCompletedSectionStatement: | ||
79 | child := stmt.GetRoot() | ||
80 | if child.Kind != ASTKindSectionStatement { | ||
81 | return NewParseError(fmt.Sprintf("unsupported child statement: %T", child)) | ||
82 | } | ||
83 | |||
84 | name := string(child.Root.Raw()) | ||
85 | v.Sections.container[name] = Section{} | ||
86 | v.scope = name | ||
87 | default: | ||
88 | return NewParseError(fmt.Sprintf("unsupported statement: %s", stmt.Kind)) | ||
89 | } | ||
90 | |||
91 | return nil | ||
92 | } | ||
93 | |||
94 | // Sections is a map of Section structures that represent | ||
95 | // a configuration. | ||
96 | type Sections struct { | ||
97 | container map[string]Section | ||
98 | } | ||
99 | |||
100 | // GetSection will return section p. If section p does not exist, | ||
101 | // false will be returned in the second parameter. | ||
102 | func (t Sections) GetSection(p string) (Section, bool) { | ||
103 | v, ok := t.container[p] | ||
104 | return v, ok | ||
105 | } | ||
106 | |||
107 | // values represents a map of union values. | ||
108 | type values map[string]Value | ||
109 | |||
110 | // List will return a list of all sections that were successfully | ||
111 | // parsed. | ||
112 | func (t Sections) List() []string { | ||
113 | keys := make([]string, len(t.container)) | ||
114 | i := 0 | ||
115 | for k := range t.container { | ||
116 | keys[i] = k | ||
117 | i++ | ||
118 | } | ||
119 | |||
120 | sort.Strings(keys) | ||
121 | return keys | ||
122 | } | ||
123 | |||
124 | // Section contains a name and values. This represent | ||
125 | // a sectioned entry in a configuration file. | ||
126 | type Section struct { | ||
127 | Name string | ||
128 | values values | ||
129 | } | ||
130 | |||
131 | // Has will return whether or not an entry exists in a given section | ||
132 | func (t Section) Has(k string) bool { | ||
133 | _, ok := t.values[k] | ||
134 | return ok | ||
135 | } | ||
136 | |||
137 | // ValueType will returned what type the union is set to. If | ||
138 | // k was not found, the NoneType will be returned. | ||
139 | func (t Section) ValueType(k string) (ValueType, bool) { | ||
140 | v, ok := t.values[k] | ||
141 | return v.Type, ok | ||
142 | } | ||
143 | |||
144 | // Bool returns a bool value at k | ||
145 | func (t Section) Bool(k string) bool { | ||
146 | return t.values[k].BoolValue() | ||
147 | } | ||
148 | |||
149 | // Int returns an integer value at k | ||
150 | func (t Section) Int(k string) int64 { | ||
151 | return t.values[k].IntValue() | ||
152 | } | ||
153 | |||
154 | // Float64 returns a float value at k | ||
155 | func (t Section) Float64(k string) float64 { | ||
156 | return t.values[k].FloatValue() | ||
157 | } | ||
158 | |||
159 | // String returns the string value at k | ||
160 | func (t Section) String(k string) string { | ||
161 | _, ok := t.values[k] | ||
162 | if !ok { | ||
163 | return "" | ||
164 | } | ||
165 | return t.values[k].StringValue() | ||
166 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/walker.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/walker.go new file mode 100644 index 0000000..99915f7 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/walker.go | |||
@@ -0,0 +1,25 @@ | |||
1 | package ini | ||
2 | |||
3 | // Walk will traverse the AST using the v, the Visitor. | ||
4 | func Walk(tree []AST, v Visitor) error { | ||
5 | for _, node := range tree { | ||
6 | switch node.Kind { | ||
7 | case ASTKindExpr, | ||
8 | ASTKindExprStatement: | ||
9 | |||
10 | if err := v.VisitExpr(node); err != nil { | ||
11 | return err | ||
12 | } | ||
13 | case ASTKindStatement, | ||
14 | ASTKindCompletedSectionStatement, | ||
15 | ASTKindNestedSectionStatement, | ||
16 | ASTKindCompletedNestedSectionStatement: | ||
17 | |||
18 | if err := v.VisitStatement(node); err != nil { | ||
19 | return err | ||
20 | } | ||
21 | } | ||
22 | } | ||
23 | |||
24 | return nil | ||
25 | } | ||
diff --git a/vendor/github.com/aws/aws-sdk-go/internal/ini/ws_token.go b/vendor/github.com/aws/aws-sdk-go/internal/ini/ws_token.go new file mode 100644 index 0000000..7ffb4ae --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/internal/ini/ws_token.go | |||
@@ -0,0 +1,24 @@ | |||
1 | package ini | ||
2 | |||
3 | import ( | ||
4 | "unicode" | ||
5 | ) | ||
6 | |||
7 | // isWhitespace will return whether or not the character is | ||
8 | // a whitespace character. | ||
9 | // | ||
10 | // Whitespace is defined as a space or tab. | ||
11 | func isWhitespace(c rune) bool { | ||
12 | return unicode.IsSpace(c) && c != '\n' && c != '\r' | ||
13 | } | ||
14 | |||
15 | func newWSToken(b []rune) (Token, int, error) { | ||
16 | i := 0 | ||
17 | for ; i < len(b); i++ { | ||
18 | if !isWhitespace(b[i]) { | ||
19 | break | ||
20 | } | ||
21 | } | ||
22 | |||
23 | return newToken(TokenWS, b[:i], NoneType), i, nil | ||
24 | } | ||