Remove last, add unscan and rescan, add handle for if not exist, just gets skipped for now

This commit is contained in:
Pablu
2025-10-28 13:16:19 +01:00
parent cd5f72bfbe
commit 396b531013
4 changed files with 69 additions and 58 deletions

View File

@@ -20,6 +20,7 @@ const (
RPAREN
COMMA
// Keywords
CREATE
TABLE
@@ -47,6 +48,8 @@ var keywords map[string]Token = map[string]Token{
"TEXT": TEXT,
"INTEGER": INTEGER,
"NULL": NULL,
"IF": IF,
"EXISTS": EXISTS,
}
type Position struct {

View File

@@ -7,12 +7,15 @@ import (
)
type Parser struct {
s *Lexer
last struct {
pos Position
tok Token
lit string
}
s *Lexer
buf LexRes
}
type LexRes struct {
pos Position
tok Token
lit string
avail bool
}
func NewParser(r io.Reader) *Parser {
@@ -27,25 +30,37 @@ func (p *Parser) Parse() (*CreateTableStatement, error) {
return nil, io.EOF
}
if !p.expectSequence(TABLE, IDENT) {
if !p.expectNext(TABLE) {
return nil, p.unexpectedToken()
}
tok, ok = p.expectOne(IDENT, IF)
if !ok {
return nil, p.unexpectedToken(IDENT, IF)
} else if tok == IF && !p.expectSequence(NOT, EXISTS, IDENT) {
return nil, p.unexpectedToken()
}
_, _, lit := p.rescan()
stmt := CreateTableStatement{
TableName: p.last.lit,
TableName: lit,
Columns: make([]Column, 0),
}
if !p.expectNext(LPAREN) {
return nil, p.unexpectedToken(LPAREN)
}
for {
lastTok := p.last.tok
_, tok, _ := p.scan()
switch tok {
case RPAREN:
if !p.expectNext(SEMI) {
return nil, p.unexpectedToken(SEMI)
}
return &stmt, nil
case IDENT:
column, err := p.parseColumn()
if err != nil {
@@ -53,24 +68,11 @@ func (p *Parser) Parse() (*CreateTableStatement, error) {
}
stmt.Columns = append(stmt.Columns, column)
case RPAREN:
if !p.expectNext(SEMI) {
return nil, p.unexpectedToken(SEMI)
}
return &stmt, nil
case SEMI:
if lastTok != RPAREN {
return nil, p.unexpectedToken(RPAREN)
}
return &stmt, nil
case FOREIGN:
if !p.expectSequence(KEY, LPAREN, IDENT) {
return nil, p.unexpectedToken()
}
columnName := p.last.lit
_, _, columnName := p.rescan()
if !p.expectSequence(RPAREN, REFERENCES) {
return nil, p.unexpectedToken()
@@ -87,31 +89,31 @@ func (p *Parser) Parse() (*CreateTableStatement, error) {
stmt.Columns[column].Extra = append(stmt.Columns[column].Extra, ref)
case COMMA:
continue
default:
return nil, p.unexpectedToken(IDENT, RPAREN, SEMI, FOREIGN)
return nil, p.unexpectedToken(IDENT, RPAREN, FOREIGN, COMMA)
}
}
}
func (p *Parser) parseColumn() (Column, error) {
column := Column{Name: p.last.lit, Extra: make([]string, 0)}
_, _, lit := p.rescan()
column := Column{Name: lit, Extra: make([]string, 0)}
_, tok, lit := p.scan()
switch tok {
case TEXT:
fallthrough
case INTEGER:
column.Type = lit
default:
if _, ok := p.expectOne(TEXT, INTEGER); !ok {
return Column{}, p.unexpectedToken(TEXT, INTEGER)
}
_, _, column.Type = p.rescan()
for {
_, tok, lit := p.scan()
switch tok {
case COMMA:
fallthrough
return column, nil
case RPAREN:
p.unscan()
return column, nil
case PRIMARY:
@@ -120,7 +122,8 @@ func (p *Parser) parseColumn() (Column, error) {
if _, ok := p.expectOne(NULL, KEY); !ok {
return Column{}, p.unexpectedToken(NULL, KEY)
}
column.Extra = append(column.Extra, fmt.Sprintf("%v_%v", lit, p.last.lit))
_, _, rlit := p.rescan()
column.Extra = append(column.Extra, fmt.Sprintf("%v_%v", lit, rlit))
case REFERENCES:
ref, err := p.references()
@@ -128,6 +131,7 @@ func (p *Parser) parseColumn() (Column, error) {
return Column{}, err
}
column.Extra = append(column.Extra, ref)
fmt.Println(ref)
default:
return Column{}, p.unexpectedToken(COMMA, RPAREN, PRIMARY, NOT, REFERENCES)
@@ -137,22 +141,23 @@ func (p *Parser) parseColumn() (Column, error) {
func (p *Parser) unexpectedToken(expected ...Token) error {
l := len(expected)
pos, tok, lit := p.rescan()
if l <= 0 {
return fmt.Errorf("Encountered unexpected token: %v lit: '%v' on pos: %v", p.last.tok, p.last.lit, p.last.pos)
return fmt.Errorf("Encountered unexpected token: %v lit: '%v' on pos: %v", tok, lit, pos)
} else if l == 1 {
return fmt.Errorf(
"Encountered unexpected token: %v lit: '%v' on pos: %v, expected %v",
p.last.tok,
p.last.lit,
p.last.pos,
tok,
lit,
pos,
expected[0],
)
} else {
return fmt.Errorf(
"Encountered unexpected token: %v lit: '%v' on pos: %v, expected one of '%v'",
p.last.tok,
p.last.lit,
p.last.pos,
tok,
lit,
pos,
arrayToString(expected, ", "),
)
}
@@ -162,13 +167,13 @@ func (p *Parser) references() (string, error) {
if !p.expectNext(IDENT) {
return "", p.unexpectedToken(IDENT)
}
referenceTableName := p.last.lit
_, _, referenceTableName := p.rescan()
if !p.expectSequence(LPAREN, IDENT) {
return "", p.unexpectedToken()
}
referenceColumnName := p.last.lit
_, _, referenceColumnName := p.rescan()
if !p.expectNext(RPAREN) {
return "", p.unexpectedToken(RPAREN)
@@ -201,17 +206,22 @@ func (p *Parser) expectOne(token ...Token) (Token, bool) {
}
func (p *Parser) scan() (Position, Token, string) {
pos, tok, lit := p.s.Lex()
// fmt.Printf("Scanning next Token: %v | pos: %v | lit: %v\n", tok, pos, lit)
p.last = struct {
pos Position
tok Token
lit string
}{
pos,
tok,
lit,
if p.buf.avail {
p.buf.avail = false
return p.buf.pos, p.buf.tok, p.buf.lit
}
pos, tok, lit := p.s.Lex()
p.buf.pos, p.buf.tok, p.buf.lit = pos, tok, lit
return pos, tok, lit
}
func (p *Parser) unscan() {
p.buf.avail = true
}
func (p *Parser) rescan() (Position, Token, string) {
p.unscan()
return p.scan()
}