parser: fix statement parsing

This commit is contained in:
Asdine El Hrychy
2023-11-26 22:18:19 +04:00
parent 389b2dc616
commit acfecdcb82
2 changed files with 37 additions and 18 deletions

View File

@@ -80,28 +80,37 @@ func (p *Parser) ParseQuery() (query.Query, error) {
// ParseQuery parses a Genji SQL string and returns a Query. // ParseQuery parses a Genji SQL string and returns a Query.
func (p *Parser) Parse(fn func(statement.Statement) error) error { func (p *Parser) Parse(fn func(statement.Statement) error) error {
semi := true
for { for {
if tok, pos, lit := p.ScanIgnoreWhitespace(); tok == scanner.EOF { err := p.skipMany(scanner.SEMICOLON)
if err != nil {
return err
}
end, err := p.parseOptional(scanner.EOF)
if err != nil {
return err
}
if end {
return nil return nil
} else if tok == scanner.SEMICOLON { }
semi = true
} else { s, err := p.ParseStatement()
if !semi { if err != nil {
return newParseError(scanner.Tokstr(tok, lit), []string{";"}, pos) return err
} }
p.Unscan()
s, err := p.ParseStatement() tok, pos, lit := p.ScanIgnoreWhitespace()
if err != nil { switch tok {
return err case scanner.EOF:
} return fn(s)
case scanner.SEMICOLON:
err = fn(s) err = fn(s)
if err != nil { if err != nil {
return err return err
} }
default:
semi = false p.Unscan()
return newParseError(scanner.Tokstr(tok, lit), []string{";"}, pos)
} }
} }
} }
@@ -142,6 +151,16 @@ func (p *Parser) ParseStatement() (statement.Statement, error) {
}, pos) }, pos)
} }
func (p *Parser) skipMany(tok scanner.Token) error {
for {
t, _, _ := p.ScanIgnoreWhitespace()
if t != tok {
p.Unscan()
return nil
}
}
}
// parseCondition parses the "WHERE" clause of the query, if it exists. // parseCondition parses the "WHERE" clause of the query, if it exists.
func (p *Parser) parseCondition() (expr.Expr, error) { func (p *Parser) parseCondition() (expr.Expr, error) {
// Check if the WHERE token exists. // Check if the WHERE token exists.

View File

@@ -27,13 +27,13 @@ func (p *Parser) parseSelectStatement() (*statement.SelectStmt, error) {
// Parse limit: "LIMIT expr" // Parse limit: "LIMIT expr"
stmt.LimitExpr, err = p.parseLimit() stmt.LimitExpr, err = p.parseLimit()
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "failed to parse LIMIT clause")
} }
// Parse offset: "OFFSET expr" // Parse offset: "OFFSET expr"
stmt.OffsetExpr, err = p.parseOffset() stmt.OffsetExpr, err = p.parseOffset()
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "failed to parse OFFSET clause")
} }
return stmt, nil return stmt, nil