feature: parser
This commit is contained in:
196
parser/parser.go
196
parser/parser.go
@@ -1 +1,197 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sfdl/scanner"
|
||||
)
|
||||
|
||||
type Parser struct {
|
||||
sc *scanner.Scanner
|
||||
tok scanner.Token
|
||||
}
|
||||
|
||||
func NewParser(sc *scanner.Scanner) *Parser {
|
||||
p := &Parser{sc: sc}
|
||||
p.nextToken()
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *Parser) nextToken() {
|
||||
p.tok = p.sc.GetToken()
|
||||
}
|
||||
|
||||
func (p *Parser) errorf(format string, args ...interface{}) {
|
||||
msg := fmt.Sprintf(format, args...)
|
||||
panic("Syntax error: " + msg)
|
||||
}
|
||||
|
||||
func (p *Parser) match(t scanner.TokenType) {
|
||||
if p.tok.Type != t {
|
||||
p.errorf("expect %v, got %v (lexeme=%q)",
|
||||
t, p.tok.Type, p.tok.Lexeme)
|
||||
}
|
||||
p.nextToken()
|
||||
}
|
||||
|
||||
// Expression → Term { (PLUS | MINUS) Term }
|
||||
func (p *Parser) parseExpression() *ExprNode {
|
||||
left := p.parseTerm()
|
||||
for p.tok.Type == scanner.PLUS || p.tok.Type == scanner.MINUS {
|
||||
op := p.tok.Type
|
||||
p.match(op)
|
||||
right := p.parseTerm()
|
||||
left = NewBinaryNode(op, left, right)
|
||||
}
|
||||
return left
|
||||
}
|
||||
|
||||
// Term → Factor { (MUL | DIV) Factor }
|
||||
func (p *Parser) parseTerm() *ExprNode {
|
||||
left := p.parseFactor()
|
||||
for p.tok.Type == scanner.MUL || p.tok.Type == scanner.DIV {
|
||||
op := p.tok.Type
|
||||
p.match(op)
|
||||
right := p.parseFactor()
|
||||
left = NewBinaryNode(op, left, right)
|
||||
}
|
||||
return left
|
||||
}
|
||||
|
||||
// Factor → (PLUS | MINUS) Factor | Component
|
||||
func (p *Parser) parseFactor() *ExprNode {
|
||||
if p.tok.Type == scanner.PLUS || p.tok.Type == scanner.MINUS {
|
||||
op := p.tok.Type
|
||||
p.match(op)
|
||||
child := p.parseFactor()
|
||||
return NewUnaryNode(op, child)
|
||||
}
|
||||
return p.parseComponent()
|
||||
}
|
||||
|
||||
// Component → Atom [ POWER Component ]
|
||||
func (p *Parser) parseComponent() *ExprNode {
|
||||
left := p.parseAtom()
|
||||
if p.tok.Type == scanner.POWER {
|
||||
p.match(scanner.POWER)
|
||||
right := p.parseComponent() // 右结合
|
||||
left = NewBinaryNode(scanner.POWER, left, right)
|
||||
}
|
||||
return left
|
||||
}
|
||||
|
||||
// Atom → CONST_ID
|
||||
//
|
||||
// | T
|
||||
// | FUNC L_BRACKET Expression R_BRACKET
|
||||
// | L_BRACKET Expression R_BRACKET
|
||||
func (p *Parser) parseAtom() *ExprNode {
|
||||
switch p.tok.Type {
|
||||
case scanner.CONST_ID:
|
||||
node := NewConstNode(p.tok.Value)
|
||||
p.nextToken()
|
||||
return node
|
||||
case scanner.T:
|
||||
p.nextToken()
|
||||
return NewTNode()
|
||||
case scanner.FUNC:
|
||||
fn := p.tok.Func
|
||||
p.nextToken()
|
||||
p.match(scanner.L_BRACKET)
|
||||
child := p.parseExpression()
|
||||
p.match(scanner.R_BRACKET)
|
||||
return NewFuncNode(fn, child)
|
||||
case scanner.L_BRACKET:
|
||||
p.match(scanner.L_BRACKET)
|
||||
node := p.parseExpression()
|
||||
p.match(scanner.R_BRACKET)
|
||||
return node
|
||||
default:
|
||||
p.errorf("unexpected token in Atom: %v (lexeme=%q)", p.tok.Type, p.tok.Lexeme)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Parse all
|
||||
func (p *Parser) Parse() {
|
||||
for p.tok.Type != scanner.NONTOKEN {
|
||||
p.parseStatement()
|
||||
p.match(scanner.SEMICO)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) parseStatement() {
|
||||
switch p.tok.Type {
|
||||
case scanner.ORIGIN:
|
||||
p.parseOriginStatement()
|
||||
case scanner.SCALE:
|
||||
p.parseScaleStatement()
|
||||
case scanner.ROT:
|
||||
p.parseRotStatement()
|
||||
case scanner.FOR:
|
||||
p.parseForStatement()
|
||||
default:
|
||||
p.errorf("unknown statement start: %v (lexeme=%q)", p.tok.Type, p.tok.Lexeme)
|
||||
}
|
||||
}
|
||||
|
||||
// ORIGIN IS ( Expression , Expression )
|
||||
func (p *Parser) parseOriginStatement() {
|
||||
p.match(scanner.ORIGIN)
|
||||
p.match(scanner.IS)
|
||||
p.match(scanner.L_BRACKET)
|
||||
xExpr := p.parseExpression()
|
||||
p.match(scanner.COMMA)
|
||||
yExpr := p.parseExpression()
|
||||
p.match(scanner.R_BRACKET)
|
||||
|
||||
// todo:
|
||||
// semantices.SetOrigin(xExpr, yExpr)
|
||||
fmt.Println("Parsed ORIGIN", xExpr, yExpr)
|
||||
}
|
||||
|
||||
// SCALE IS ( Expression , Expression )
|
||||
func (p *Parser) parseScaleStatement() {
|
||||
p.match(scanner.SCALE)
|
||||
p.match(scanner.IS)
|
||||
p.match(scanner.L_BRACKET)
|
||||
xExpr := p.parseExpression()
|
||||
p.match(scanner.COMMA)
|
||||
yExpr := p.parseExpression()
|
||||
p.match(scanner.R_BRACKET)
|
||||
|
||||
fmt.Println("Parsed SCALE", xExpr, yExpr)
|
||||
}
|
||||
|
||||
// ROT IS Expression
|
||||
func (p *Parser) parseRotStatement() {
|
||||
p.match(scanner.ROT)
|
||||
p.match(scanner.IS)
|
||||
angleExpr := p.parseExpression()
|
||||
|
||||
fmt.Println("Parsed ROT", angleExpr)
|
||||
}
|
||||
|
||||
// FOR T FROM Expression TO Expression STEP Expression
|
||||
//
|
||||
// DRAW ( Expression , Expression )
|
||||
func (p *Parser) parseForStatement() {
|
||||
p.match(scanner.FOR)
|
||||
p.match(scanner.T)
|
||||
p.match(scanner.FROM)
|
||||
start := p.parseExpression()
|
||||
p.match(scanner.TO)
|
||||
end := p.parseExpression()
|
||||
p.match(scanner.STEP)
|
||||
step := p.parseExpression()
|
||||
p.match(scanner.DRAW)
|
||||
p.match(scanner.L_BRACKET)
|
||||
xExpr := p.parseExpression()
|
||||
p.match(scanner.COMMA)
|
||||
yExpr := p.parseExpression()
|
||||
p.match(scanner.R_BRACKET)
|
||||
|
||||
fmt.Println("Parsed FOR", start, end, step, xExpr, yExpr)
|
||||
|
||||
// todo:
|
||||
// semantices.DrawLoop(start, end, step, xExpr, yExpr)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user