parser.go (2666B)
1 package parser 2 3 import ( 4 "fmt" 5 "mighty/lexer" 6 ) 7 8 type Expr interface{ expr_node() } 9 10 type Ident struct{ Name string } 11 12 func (Ident) expr_node() {} 13 14 type LitInt struct{ Value string } 15 16 func (LitInt) expr_node() {} 17 18 type LitStr struct{ Value string } 19 20 func (LitStr) expr_node() {} 21 22 type Binary struct { 23 Op lexer.Kind 24 Left Expr 25 Right Expr 26 } 27 28 func (Binary) expr_node() {} 29 30 type Call struct { 31 Callee Expr 32 Args []Expr 33 } 34 35 func (Call) expr_node() {} 36 37 type Parser struct { 38 tokens []lexer.Token 39 pos int 40 errs []error 41 } 42 43 func ParseExpr(tokens []lexer.Token) (Expr, []error) { 44 45 p := Parser{tokens: tokens} 46 expr := p.expr(0) 47 48 return expr, p.errs 49 } 50 51 func (p *Parser) expr(minPrec int) Expr { 52 53 left := p.postfix() 54 55 for { 56 op := p.peek().Kind 57 prec := precedence(op) 58 59 if prec < minPrec { 60 break 61 } 62 63 p.advance() 64 65 right := p.expr(prec + 1) 66 67 left = Binary{Op: op, Left: left, Right: right} 68 } 69 70 return left 71 72 } 73 74 func (p *Parser) postfix() Expr { 75 left := p.primary() 76 77 for p.match(lexer.LParen) { 78 var args []Expr 79 80 if !p.check(lexer.RParen) { 81 82 for { 83 args = append(args, p.expr(0)) 84 if !p.match(lexer.Comma) { 85 break 86 } 87 } 88 } 89 p.expect(lexer.RParen, "expected ')' after call arguments") 90 left = Call{Callee: left, Args: args} 91 92 } 93 return left 94 95 } 96 97 func (p *Parser) primary() Expr { 98 tok := p.advance() 99 100 switch tok.Kind { 101 102 case lexer.Ident: 103 return Ident{Name: tok.Value} 104 case lexer.LiteralInt: 105 return LitInt{Value: tok.Value} 106 case lexer.LiteralString: 107 return LitStr{Value: tok.Value} 108 case lexer.LParen: 109 expr := p.expr(0) 110 p.expect(lexer.RParen, "expected ')' after expression") 111 return expr 112 default: 113 p.err(tok, "expected expression") 114 return Ident{Name: "<error>"} 115 } 116 } 117 118 func precedence(kind lexer.Kind) int { 119 switch kind { 120 case lexer.Plus, lexer.Minus: 121 return 10 122 case lexer.Star, lexer.Slash: 123 return 20 124 default: 125 return -1 126 } 127 } 128 129 func (p *Parser) peek() lexer.Token { 130 131 if p.pos >= len(p.tokens) { 132 return p.tokens[len(p.tokens)-1] 133 } 134 135 return p.tokens[p.pos] 136 } 137 138 func (p *Parser) advance() lexer.Token { 139 140 tok := p.peek() 141 if p.pos < len(p.tokens) { 142 p.pos++ 143 } 144 return tok 145 } 146 147 func (p *Parser) check(kind lexer.Kind) bool { 148 return p.peek().Kind == kind 149 } 150 151 func (p *Parser) match(kind lexer.Kind) bool { 152 if !p.check(kind) { 153 return false 154 } 155 p.advance() 156 return true 157 } 158 159 func (p *Parser) expect(kind lexer.Kind, msg string) lexer.Token { 160 if p.check(kind) { 161 return p.advance() 162 } 163 164 p.err(p.peek(), msg) 165 return lexer.Token{Kind: kind} 166 } 167 168 func (p *Parser) err(tok lexer.Token, msg string) { 169 p.errs = append(p.errs, fmt.Errorf("%d:%d %s", tok.Line, tok.Col, msg)) 170 } 171 172 // 173 // 174 // 175 // 176 // 177 // 178 // 179 // 180 //