198 lines
4.3 KiB
Go
198 lines
4.3 KiB
Go
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)
|
|
}
|