Skip to content

Commit

Permalink
progress
Browse files Browse the repository at this point in the history
  • Loading branch information
chirst committed Aug 30, 2024
1 parent f833cf9 commit 80e028d
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 16 deletions.
7 changes: 7 additions & 0 deletions compiler/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ type IntLit struct {

func (*IntLit) Type() string { return "IntLit" }

// StringLit is an expression that is a literal string such as "'asdf'".
type StringLit struct {
Value string
}

func (*StringLit) Type() string { return "StringLit" }

// FunctionExpr is an expression that represents a function.
type FunctionExpr struct {
Name string
Expand Down
78 changes: 62 additions & 16 deletions compiler/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,14 @@ func (p *parser) parseResultColumn() (*ResultColumn, error) {
}
}
}
err := p.parseExpression(resultColumn)
p.rewind()
expr := p.parseExpression(0)
// handle err
// if err != nil {
// return nil, err
// }
resultColumn.Expression = expr
err := p.parseAlias(resultColumn)
return resultColumn, err
}

Expand All @@ -136,25 +143,59 @@ func (p *parser) parseCountFunction(resultColumn *ResultColumn) error {
return p.parseAlias(resultColumn)
}

func (p *parser) parseExpression(resultColumn *ResultColumn) error {
r := p.tokens[p.end]
switch r.tokenType {
case tkIdentifier:
// r2 := p.nextNonSpace()
// tODO
case tkLiteral:
panic("literal in expression not handled")
case tkNumeric:
vi, err := strconv.Atoi(r.value)
// Vaughan Pratt's top down operator precedence parsing algorithm.
// Definitions:
// - Left binding power (LBP) an integer representing operator precedence level.
// - Null denotation (NUD) nothing to it's left (prefix).
// - Left denotation (LED) something to it's left (infix).
// - Right binding power (RBP) parse prefix operator then iteratively parse
// infix expressions.
//
// Begin with rbp 0
func (p *parser) parseExpression(rbp int) Expr {
// parse prefix into leftToken i.e. if the first token is a prefix operator
// take that operator and create a unary expression. If the first token is
// literal parse into the literal. If something else throw.
first := p.nextNonSpace()
var left Expr
if first.tokenType == tkLiteral {
left = &StringLit{Value: first.value}
} else if first.tokenType == tkNumeric {
intValue, err := strconv.Atoi(first.value)
if err != nil {
return err
panic("sad")
}
resultColumn.Expression = &IntLit{
Value: vi,
left = &IntLit{Value: intValue}
} else {
panic("failed to parse null denotation")
}
for {
nextToken := p.peekNextNonSpace()
if nextToken.tokenType == tkOperator {
nextPrecedence := opPrecedence[nextToken.value]
if nextPrecedence <= rbp {
break
} else {
p.nextNonSpace()
left = &BinaryExpr{
Left: left,
Operator: nextToken.value,
Right: p.parseExpression(nextPrecedence),
}
continue
}
} else {
break
}
return p.parseAlias(resultColumn)
}
panic("unhandled expression token")
return left
// parse the next expression and get the lbp. If it is the end of input
// return 0 to stop parsing. This next expression will be a infix parselet.
// while rbp < lbp
// Get an infix parselet with the left being the left of the binary op.
// Create the new expression and assign it to left. These parselets should
// be recursively calling parse sometimes.
// return left as it is the entire parsed expression
}

func (p *parser) parseAlias(resultColumn *ResultColumn) error {
Expand Down Expand Up @@ -321,3 +362,8 @@ func (p *parser) peekNonSpaceBy(next int) token {
}
return p.tokens[tmpEnd]
}

func (p *parser) rewind() token {
p.end = p.end - 1
return p.tokens[p.end]
}

0 comments on commit 80e028d

Please sign in to comment.