Working select statements for know tables, with and without semi at the end

This commit is contained in:
Pablu
2025-12-01 16:36:04 +01:00
parent 6182129022
commit 694bbb7934
3 changed files with 284 additions and 24 deletions

View File

@@ -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