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) originStatement(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) scaleStatement(xExpr, yExpr) } // ROT IS Expression func (p *Parser) parseRotStatement() { p.match(scanner.ROT) p.match(scanner.IS) angleExpr := p.parseExpression() rotStatement(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) forStatement(start, end, step, xExpr, yExpr) }