Working select statements for know tables, with and without semi at the end
This commit is contained in:
@@ -23,18 +23,75 @@ func NewParser(r io.Reader) *Parser {
|
||||
}
|
||||
|
||||
func (p *Parser) Parse() (Statement, error) {
|
||||
tok, ok := p.expectOne(CREATE, EOF)
|
||||
tok, ok := p.expectOne(CREATE, EOF, SELECT)
|
||||
if !ok {
|
||||
return nil, p.unexpectedToken(CREATE, EOF)
|
||||
} else if tok == EOF {
|
||||
return nil, io.EOF
|
||||
}
|
||||
|
||||
switch tok {
|
||||
case EOF:
|
||||
return nil, io.EOF
|
||||
case CREATE:
|
||||
return p.parseCreateTable()
|
||||
case SELECT:
|
||||
return p.parseSelect()
|
||||
default:
|
||||
panic("SHOULD NEVER BE REACHED")
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) parseSelect() (*SelectStatement, error) {
|
||||
tok, ok := p.expectOne(ASTERIKS, IDENT)
|
||||
if !ok {
|
||||
return nil, p.unexpectedToken(ASTERIKS, IDENT)
|
||||
}
|
||||
|
||||
fields := make([]string, 1)
|
||||
fields[0] = "*"
|
||||
if tok == IDENT {
|
||||
_, _, n := p.rescan()
|
||||
fields[0] = n
|
||||
for {
|
||||
tok, ok := p.expectOne(COMMA, FROM)
|
||||
if !ok {
|
||||
return nil, p.unexpectedToken(COMMA, FROM)
|
||||
}
|
||||
if tok == FROM {
|
||||
p.unscan()
|
||||
break
|
||||
}
|
||||
|
||||
if !p.expectNext(IDENT) {
|
||||
return nil, p.unexpectedToken(IDENT)
|
||||
}
|
||||
_, _, n := p.rescan()
|
||||
fields = append(fields, n)
|
||||
}
|
||||
}
|
||||
|
||||
if !p.expectSequence(FROM, IDENT) {
|
||||
return nil, p.unexpectedToken()
|
||||
}
|
||||
|
||||
_, _, tableName := p.rescan()
|
||||
if !p.consumeUntilOne(50, SEMI, EOF) {
|
||||
return nil, fmt.Errorf("Expected semicolon but never found after 50 tries")
|
||||
}
|
||||
|
||||
return &SelectStatement{
|
||||
From: tableName,
|
||||
Fields: fields,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseCreateTable() (*CreateTableStatement, error) {
|
||||
if !p.expectNext(TABLE) {
|
||||
return nil, p.unexpectedToken()
|
||||
}
|
||||
|
||||
tok, ok = p.expectOne(IDENT, IF)
|
||||
tok, ok := p.expectOne(IDENT, IF)
|
||||
if !ok {
|
||||
return nil, p.unexpectedToken(IDENT, IF)
|
||||
} else if tok == IF && !p.expectSequence(NOT, EXISTS, IDENT) {
|
||||
@@ -237,6 +294,28 @@ func (p *Parser) expectOne(token ...Token) (Token, bool) {
|
||||
return tok, ok
|
||||
}
|
||||
|
||||
func (p *Parser) consumeUntilOne(max int, token ...Token) bool {
|
||||
for range max {
|
||||
_, tok, _ := p.scan()
|
||||
if slices.ContainsFunc(token, func(t Token) bool {
|
||||
return tok == t
|
||||
}) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Parser) consumeUntil(token Token, max int) bool {
|
||||
for range max {
|
||||
_, tok, _ := p.scan()
|
||||
if tok == token {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Parser) scan() (Position, Token, string) {
|
||||
if p.buf.avail {
|
||||
p.buf.avail = false
|
||||
|
||||
Reference in New Issue
Block a user