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
case isAlphaNumeric(r) || r == ':':
case isAlpha(r) || r == ':':
l.backup()
return lexKeywordOrIdentifier
case r == '(':
@ -515,7 +515,7 @@ func lexInsideBraces(l *lexer) stateFn {
return l.errorf("unexpected end of input inside braces")
case isSpace(r):
return lexSpace
case unicode.IsLetter(r) || r == '_':
case isAlpha(r):
l.backup()
return lexIdentifier
case r == ',':
@ -703,5 +703,10 @@ func isEndOfLine(r rune) bool {
// isAlphaNumeric reports whether r is an alphabetic, digit, or underscore.
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",
expected: []item{{itemIdentifier, 0, "abc"}, {itemIdentifier, 4, "d"}},
}, {
input: ":bc",
expected: []item{{itemMetricIdentifier, 0, ":bc"}},
}, {
input: "0a:bc",
fail: true,
},
// Test comments.
{
@ -247,6 +253,12 @@ var tests = []struct {
{
input: `台北`,
fail: true,
}, {
input: `{台北='a'}`,
fail: true,
}, {
input: `{0a='a'}`,
fail: true,
}, {
input: `{foo='bar'}`,
expected: []item{

View File

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