@@ -5,12 +5,40 @@ package parser
55
66import (
77 "fmt"
8+ "strconv"
89
910 "github.com/cedrickchee/hou/ast"
1011 "github.com/cedrickchee/hou/lexer"
1112 "github.com/cedrickchee/hou/token"
1213)
1314
15+ // Define the precedences of the language.
16+ // These constants is able to answer: "does the * operator have a higher
17+ // precedence than the == operator? Does a prefix operator have a higher
18+ // preference than a call expression?"
19+ const (
20+ _ int = iota
21+ LOWEST // lowest possible precedence
22+ EQUALS // ==
23+ LESSGREATER // > or <
24+ SUM // +
25+ PRODUCT // *
26+ PREFIX // -X or !X
27+ CALL // myFunction(X)
28+ )
29+
30+ // Pratt parser's idea is the association of parsing functions with token types.
31+ // Whenever this token type is encountered, the parsing functions are called to
32+ // parse the appropriate expression and return an AST node that represents it.
33+ // Each token type can have up to two parsing functions associated with it,
34+ // depending on whether the token is found in a prefix or an infix position.
35+ type (
36+ prefixParseFn func () ast.Expression
37+ // This function argument is "left side" of the infix operator that’s being
38+ // parsed.
39+ infixParseFn func (ast.Expression ) ast.Expression
40+ )
41+
1442// Parser implements the parser.
1543type Parser struct {
1644 l * lexer.Lexer
@@ -19,6 +47,11 @@ type Parser struct {
1947
2048 curToken token.Token
2149 peekToken token.Token
50+
51+ // maps to get the correct prefixParseFn or infixParseFn for the current
52+ // token type.
53+ prefixParseFns map [token.TokenType ]prefixParseFn
54+ infixParseFns map [token.TokenType ]infixParseFn
2255}
2356
2457// New constructs a new Parser with a Lexer as input.
@@ -28,6 +61,13 @@ func New(l *lexer.Lexer) *Parser {
2861 errors : []string {},
2962 }
3063
64+ // Initialize the prefixParseFns map.
65+ p .prefixParseFns = make (map [token.TokenType ]prefixParseFn )
66+ p .registerPrefix (token .IDENT , p .parseIdentifier )
67+ p .registerPrefix (token .INT , p .parseIntegerLiteral )
68+ p .registerPrefix (token .BANG , p .parsePrefixExpression )
69+ p .registerPrefix (token .MINUS , p .parsePrefixExpression )
70+
3171 // Read two tokens, so curToken and peekToken are both set.
3272 p .nextToken ()
3373 p .nextToken ()
@@ -81,7 +121,7 @@ func (p *Parser) parseStatement() ast.Statement {
81121 case token .RETURN :
82122 return p .parseReturnStatement ()
83123 default :
84- return nil
124+ return p . parseExpressionStatement ()
85125 }
86126}
87127
@@ -126,6 +166,83 @@ func (p *Parser) parseReturnStatement() *ast.ReturnStatement {
126166 return stmt
127167}
128168
169+ // The top-level method that kicks off expression parsing.
170+ func (p * Parser ) parseExpressionStatement () * ast.ExpressionStatement {
171+ stmt := & ast.ExpressionStatement {Token : p .curToken }
172+
173+ stmt .Expression = p .parseExpression (LOWEST )
174+
175+ if p .peekTokenIs (token .SEMICOLON ) {
176+ p .nextToken ()
177+ }
178+
179+ return stmt
180+ }
181+
182+ // Check whether there's a parsing function associated with p.curToken.Type in
183+ // the prefix position.
184+ func (p * Parser ) parseExpression (precedence int ) ast.Expression {
185+ prefix := p .prefixParseFns [p .curToken .Type ]
186+ if prefix == nil {
187+ // noPrefixParseFnError give us better error messages when
188+ // program.Statements does not contain one statement but simply one nil.
189+ p .noPrefixParseFnError (p .curToken .Type )
190+ return nil
191+ }
192+
193+ leftExp := prefix ()
194+
195+ return leftExp
196+ }
197+
198+ func (p * Parser ) parseIdentifier () ast.Expression {
199+ // This method doesn’t advance the tokens, it doesn’t call nextToken.
200+ // That’s important.
201+ // All of our parsing functions, prefixParseFn or infixParseFn, are going to
202+ // follow this protocol:
203+ // start with curToken being the type of token you’re associated with and
204+ // return with curToken being the last token that’s part of your expression
205+ // type. Never advance the tokens too far.
206+ return & ast.Identifier {Token : p .curToken , Value : p .curToken .Literal }
207+ }
208+
209+ func (p * Parser ) noPrefixParseFnError (t token.TokenType ) {
210+ msg := fmt .Sprintf ("no prefix parse function for %s found" , t )
211+ p .errors = append (p .errors , msg )
212+ }
213+
214+ func (p * Parser ) parseIntegerLiteral () ast.Expression {
215+ lit := & ast.IntegerLiteral {Token : p .curToken }
216+
217+ value , err := strconv .ParseInt (p .curToken .Literal , 0 , 64 )
218+ if err != nil {
219+ msg := fmt .Sprintf ("could not parse %q as integer" , p .curToken .Literal )
220+ p .errors = append (p .errors , msg )
221+ return nil
222+ }
223+
224+ lit .Value = value
225+
226+ return lit
227+ }
228+
229+ func (p * Parser ) parsePrefixExpression () ast.Expression {
230+ expression := & ast.PrefixExpression {
231+ Token : p .curToken ,
232+ Operator : p .curToken .Literal ,
233+ }
234+
235+ // Advances our tokens in order to correctly parse a prefix expression
236+ // like `-5` more than one token has to be "consumed".
237+ p .nextToken ()
238+
239+ // parseExpression() value changes depending on the caller's knowledge and
240+ // its context.
241+ expression .Right = p .parseExpression (PREFIX )
242+
243+ return expression
244+ }
245+
129246// "assertion functions".
130247// Enforce the correctness of the order of tokens by checking the type of the
131248// next token.
@@ -145,3 +262,13 @@ func (p *Parser) peekTokenIs(t token.TokenType) bool {
145262func (p * Parser ) curTokenIs (t token.TokenType ) bool {
146263 return p .curToken .Type == t
147264}
265+
266+ // Helper method that add entries to the prefixParseFns map.
267+ func (p * Parser ) registerPrefix (tokenType token.TokenType , fn prefixParseFn ) {
268+ p .prefixParseFns [tokenType ] = fn
269+ }
270+
271+ // Helper method that add entries to the infixParseFns map.
272+ func (p * Parser ) registerInfix (tokenType token.TokenType , fn infixParseFn ) {
273+ p .infixParseFns [tokenType ] = fn
274+ }
0 commit comments