22#include <stdint.h>
33#include <stdio.h>
44#include <stdlib.h>
5+ #include <sys/types.h>
56
67#include "chunk.h"
78#include "common.h"
@@ -37,7 +38,7 @@ typedef enum
3738 PREC_PRIMARY
3839} Precedence ;
3940
40- typedef void (* ParseFn )();
41+ typedef void (* ParseFn )(bool can_assign );
4142
4243typedef struct
4344{
@@ -178,7 +179,23 @@ static void declaration();
178179static ParseRule * get_rule (TokenType type );
179180static void parse_precedence (Precedence precedence );
180181
181- static void binary ()
182+ static uint8_t identifier_constant (Token * name )
183+ {
184+ return make_constant (OBJ_VAL (copy_string (name -> start , name -> length )));
185+ }
186+
187+ static uint8_t parse_variable (const char * error_message )
188+ {
189+ consume (TOKEN_IDENTIFIER , error_message );
190+ return identifier_constant (& parser .previous );
191+ }
192+
193+ static void define_variable (uint8_t global )
194+ {
195+ emit_bytes (OP_DEFINE_GLOBAL , global );
196+ }
197+
198+ static void binary (bool can_assign )
182199{
183200 TokenType operator_type = parser .previous .type ;
184201
@@ -222,7 +239,7 @@ static void binary()
222239 }
223240}
224241
225- static void literal ()
242+ static void literal (bool can_assign )
226243{
227244 switch (parser .previous .type )
228245 {
@@ -240,25 +257,42 @@ static void literal()
240257 }
241258}
242259
243- static void grouping ()
260+ static void grouping (bool can_assign )
244261{
245262 expression ();
246263 consume (TOKEN_RIGHT_PAREN , "Expect ')' after expression" );
247264}
248265
249- static void number ()
266+ static void number (bool can_assign )
250267{
251268 double value = strtod (parser .previous .start , NULL );
252269 emit_constant (NUMBER_VAL (value ));
253270}
254271
255- static void string ()
272+ static void string (bool can_assign )
256273{
257274 emit_constant (OBJ_VAL (
258275 copy_string (parser .previous .start + 1 , parser .previous .length - 2 )));
259276}
260277
261- static void unary ()
278+ static void named_variable (Token name , bool can_assign )
279+ {
280+ uint8_t arg = identifier_constant (& name );
281+ if (can_assign && match (TOKEN_EQUAL ))
282+ {
283+ expression ();
284+ emit_bytes (OP_SET_GLOBAL , arg );
285+ }
286+ else
287+ emit_bytes (OP_GET_GLOBAL , arg );
288+ }
289+
290+ static void variable (bool can_assign )
291+ {
292+ named_variable (parser .previous , can_assign );
293+ }
294+
295+ static void unary (bool can_assign )
262296{
263297 TokenType operator_type = parser .previous .type ;
264298
@@ -297,9 +331,9 @@ ParseRule rules[] = {
297331 [TOKEN_GREATER_EQUAL ] = { NULL , binary , PREC_COMPARAISON },
298332 [TOKEN_LESS ] = { NULL , binary , PREC_COMPARAISON },
299333 [TOKEN_LESS_EQUAL ] = { NULL , binary , PREC_COMPARAISON },
300- [TOKEN_STRING ] = { string , NULL , PREC_NONE },
334+ [TOKEN_STRING ] = { string , NULL , PREC_NONE },
301335 [TOKEN_NUMBER ] = { number , NULL , PREC_NONE },
302- [TOKEN_IDENTIFIER ] = { NULL , NULL , PREC_NONE },
336+ [TOKEN_IDENTIFIER ] = { variable , NULL , PREC_NONE },
303337 [TOKEN_AND ] = { NULL , NULL , PREC_NONE },
304338 [TOKEN_CLASS ] = { NULL , NULL , PREC_NONE },
305339 [TOKEN_ELSE ] = { NULL , NULL , PREC_NONE },
@@ -330,13 +364,19 @@ static void parse_precedence(Precedence precedence)
330364 error ("Expect expression" );
331365 return ;
332366 }
333- prefix_rule ();
367+ bool can_assign = precedence <= PREC_ASSIGNMENT ;
368+ prefix_rule (can_assign );
334369
335370 while (precedence <= get_rule (parser .current .type )-> precedence )
336371 {
337372 advance ();
338373 ParseFn infix_rule = get_rule (parser .previous .type )-> infix ;
339- infix_rule ();
374+ infix_rule (can_assign );
375+ }
376+
377+ if (can_assign && match (TOKEN_EQUAL ))
378+ {
379+ error ("Invalid assignment target" );
340380 }
341381}
342382
@@ -352,6 +392,19 @@ static void expression()
352392
353393// ---------------------- statements --------------------------
354394
395+ static void var_declaration ()
396+ {
397+ uint8_t global = parse_variable ("Expect variable name" );
398+
399+ if (match (TOKEN_EQUAL ))
400+ expression ();
401+ else
402+ emit_byte (OP_NIL );
403+
404+ consume (TOKEN_SEMICOLON , "Expect ';' after variable declaration" );
405+ define_variable (global );
406+ }
407+
355408static void expression_statement ()
356409{
357410 expression ();
@@ -397,7 +450,10 @@ static void synchronize()
397450
398451static void declaration ()
399452{
400- statement ();
453+ if (match (TOKEN_VAR ))
454+ var_declaration ();
455+ else
456+ statement ();
401457
402458 if (parser .panic_mode )
403459 synchronize ();
@@ -406,13 +462,9 @@ static void declaration()
406462static void statement ()
407463{
408464 if (match (TOKEN_PRINT ))
409- {
410465 print_statement ();
411- }
412466 else
413- {
414467 expression_statement ();
415- }
416468}
417469
418470static inline void init_parser ()
0 commit comments