Make parser more strict about identifiers, extract number parsing

This commit is contained in:
Fabian Reinartz 2015-05-11 11:45:23 +02:00
parent 1b3d3b4d5c
commit 969c231191
3 changed files with 34 additions and 11 deletions

View file

@ -465,7 +465,7 @@ func lexStatements(l *lexer) stateFn {
} }
} }
fallthrough fallthrough
case isAlphaNumeric(r) || r == ':': case isAlpha(r) || r == ':':
l.backup() l.backup()
return lexKeywordOrIdentifier return lexKeywordOrIdentifier
case r == '(': case r == '(':
@ -515,7 +515,7 @@ func lexInsideBraces(l *lexer) stateFn {
return l.errorf("unexpected end of input inside braces") return l.errorf("unexpected end of input inside braces")
case isSpace(r): case isSpace(r):
return lexSpace return lexSpace
case unicode.IsLetter(r) || r == '_': case isAlpha(r):
l.backup() l.backup()
return lexIdentifier return lexIdentifier
case r == ',': case r == ',':
@ -703,5 +703,10 @@ func isEndOfLine(r rune) bool {
// isAlphaNumeric reports whether r is an alphabetic, digit, or underscore. // isAlphaNumeric reports whether r is an alphabetic, digit, or underscore.
func isAlphaNumeric(r rune) bool { func isAlphaNumeric(r rune) bool {
return r == '_' || ('a' <= r && r <= 'z') || ('A' <= r && r <= 'Z') || unicode.IsDigit(r) return isAlpha(r) || unicode.IsDigit(r)
}
// isAlpha reports whether r is an alphabetic or underscore.
func isAlpha(r rune) bool {
return r == '_' || ('a' <= r && r <= 'z') || ('A' <= r && r <= 'Z')
} }

View file

@ -121,6 +121,12 @@ var tests = []struct {
}, { }, {
input: "abc d", input: "abc d",
expected: []item{{itemIdentifier, 0, "abc"}, {itemIdentifier, 4, "d"}}, expected: []item{{itemIdentifier, 0, "abc"}, {itemIdentifier, 4, "d"}},
}, {
input: ":bc",
expected: []item{{itemMetricIdentifier, 0, ":bc"}},
}, {
input: "0a:bc",
fail: true,
}, },
// Test comments. // Test comments.
{ {
@ -247,6 +253,12 @@ var tests = []struct {
{ {
input: `台北`, input: `台北`,
fail: true, fail: true,
}, {
input: `{台北='a'}`,
fail: true,
}, {
input: `{0a='a'}`,
fail: true,
}, { }, {
input: `{foo='bar'}`, input: `{foo='bar'}`,
expected: []item{ expected: []item{

View file

@ -453,6 +453,19 @@ func (p *parser) rangeSelector(vs *VectorSelector) *MatrixSelector {
return e return e
} }
// parseNumber parses a number.
func (p *parser) number(val string) float64 {
n, err := strconv.ParseInt(val, 0, 64)
f := float64(n)
if err != nil {
f, err = strconv.ParseFloat(val, 64)
}
if err != nil {
p.errorf("error parsing number: %s", err)
}
return f
}
// primaryExpr parses a primary expression. // primaryExpr parses a primary expression.
// //
// <metric_name> | <function_call> | <vector_aggregation> | <literal> // <metric_name> | <function_call> | <vector_aggregation> | <literal>
@ -460,14 +473,7 @@ func (p *parser) rangeSelector(vs *VectorSelector) *MatrixSelector {
func (p *parser) primaryExpr() Expr { func (p *parser) primaryExpr() Expr {
switch t := p.next(); { switch t := p.next(); {
case t.typ == itemNumber: case t.typ == itemNumber:
n, err := strconv.ParseInt(t.val, 0, 64) f := p.number(t.val)
f := float64(n)
if err != nil {
f, err = strconv.ParseFloat(t.val, 64)
}
if err != nil {
p.errorf("error parsing number: %s", err)
}
return &NumberLiteral{clientmodel.SampleValue(f)} return &NumberLiteral{clientmodel.SampleValue(f)}
case t.typ == itemString: case t.typ == itemString: