Support for quoted string arguments.

This commit is contained in:
Andrey Smirnov
2014-07-14 23:20:31 +04:00
parent 3601cc15ed
commit a632469890
3 changed files with 54 additions and 14 deletions

View File

@@ -13,7 +13,8 @@ type itemType int
const eof = -1
const (
itemError itemType = iota // error occurred;
itemNull itemType = iota
itemError // error occurred;
// value is text of error
itemEOF
itemLeftParen // (
@@ -46,6 +47,12 @@ func (i item) String() string {
if i.typ == itemEOF {
return "<EOL>"
}
if i.typ == itemError {
return fmt.Sprintf("error: %s", i.val)
}
if i.typ == itemNull {
return "<NULL>"
}
return i.val
}
@@ -199,19 +206,42 @@ func lexMain(l *lexer) stateFn {
}
func lexString(l *lexer) stateFn {
for {
r := l.next()
if unicode.IsSpace(r) || strings.IndexRune("()|,!{}", r) > 0 {
l.backup()
l.emit(itemString)
return lexMain(l)
r := l.next()
// quoted string
if r == '"' || r == '\'' {
quote := r
result := ""
l.ignore()
for {
r = l.next()
if r == quote {
l.ignore()
l.items <- item{itemString, result}
return lexMain
}
if r == '\\' {
r = l.next()
}
if r == eof {
return l.errorf("unexpected eof in quoted string")
}
result = result + string(r)
}
} else {
// unquoted string
for {
if unicode.IsSpace(r) || strings.IndexRune("()|,!{}", r) > 0 {
l.backup()
l.emit(itemString)
return lexMain
}
if r == eof {
l.emit(itemString)
l.emit(itemEOF)
return nil
if r == eof {
l.emit(itemString)
l.emit(itemEOF)
return nil
}
r = l.next()
}
}
}

View File

@@ -11,7 +11,7 @@ type LexerSuite struct {
var _ = Suite(&LexerSuite{})
func (s *LexerSuite) TestLexing(c *C) {
_, ch := lex("query", "package (<< 1.3), $Source | !app, data {i386}")
_, ch := lex("query", "package (<< 1.3), $Source | !\"app\", 'd\"\\a\\'ta' {i386}")
c.Check(<-ch, Equals, item{typ: itemString, val: "package"})
c.Check(<-ch, Equals, item{typ: itemLeftParen, val: "("})
@@ -24,7 +24,7 @@ func (s *LexerSuite) TestLexing(c *C) {
c.Check(<-ch, Equals, item{typ: itemNot, val: "!"})
c.Check(<-ch, Equals, item{typ: itemString, val: "app"})
c.Check(<-ch, Equals, item{typ: itemAnd, val: ","})
c.Check(<-ch, Equals, item{typ: itemString, val: "data"})
c.Check(<-ch, Equals, item{typ: itemString, val: "d\"a'ta"})
c.Check(<-ch, Equals, item{typ: itemLeftCurly, val: "{"})
c.Check(<-ch, Equals, item{typ: itemString, val: "i386"})
c.Check(<-ch, Equals, item{typ: itemRightCurly, val: "}"})
@@ -49,3 +49,9 @@ func (s *LexerSuite) TestString(c *C) {
l.Consume()
c.Check(fmt.Sprintf("%s", l.Current()), Equals, "(")
}
func (s *LexerSuite) TestError(c *C) {
l, _ := lex("query", "'package")
c.Check(fmt.Sprintf("%s", l.Current()), Equals, "error: unexpected eof in quoted string")
}

View File

@@ -74,4 +74,8 @@ func (s *SyntaxSuite) TestParsingErrors(c *C) {
l, _ = lex("query", "!package )")
_, err = parse(l)
c.Check(err, ErrorMatches, "parsing failed: unexpected token \\): expecting end of query")
l, _ = lex("query", "'package )")
_, err = parse(l)
c.Check(err, ErrorMatches, "parsing failed: unexpected token error: unexpected eof in quoted string: expecting field or package name")
}