buggy cool.y

This commit is contained in:
ridethepig 2023-03-22 08:59:04 +00:00
parent ae7236fe58
commit 4db0884baa

View File

@ -135,9 +135,34 @@
%type <class_> class %type <class_> class
/* You will want to change the following line. */ /* You will want to change the following line. */
%type <features> dummy_feature_list %type <features> feature_list
%type <feature> feature
%type <formals> formal_list
%type <formal> formal
%type <expressions> expression_list_comma
%type <expressions> expression_list_colon
%type <expression> expression
%type <cases> case_list
%type <case_> case
%type <expression> nested_let
/* Precedence declarations go here. */ /* Precedence declarations go here. */
/* No need to specify then-else precedence, the silly language forbids omitting else */
/* %precedence THEN
%precedence ELSE */
/* all other binary operations are left-associative
* assignment is right-associative,
* three comparison operations do not associate.*/
%right ASSIGN
%left NOT
%nonassoc '<' LE '='
%left '+' '-'
%left '*' '/'
%precedence ISVOID
%precedence '~'
%precedence '@'
%precedence '.'
%% %%
@ -154,21 +179,142 @@
| class_list class /* several classes */ | class_list class /* several classes */
{ $$ = append_Classes($1,single_Classes($2)); { $$ = append_Classes($1,single_Classes($2));
parse_results = $$; } parse_results = $$; }
/* TODO: I guess `parse_results` is only needed in the top-most class_list*/
; ;
/* If no parent is specified, the class inherits from the Object class. */ /* If no parent is specified, the class inherits from the Object class. */
class : CLASS TYPEID '{' dummy_feature_list '}' ';' class : CLASS TYPEID '{' feature_list '}' ';'
{ $$ = class_($2,idtable.add_string("Object"),$4, { $$ = class_($2,idtable.add_string("Object"),$4,
stringtable.add_string(curr_filename)); } stringtable.add_string(curr_filename)); }
| CLASS TYPEID INHERITS TYPEID '{' dummy_feature_list '}' ';' | CLASS TYPEID INHERITS TYPEID '{' feature_list '}' ';'
{ $$ = class_($2,$4,$6,stringtable.add_string(curr_filename)); } { $$ = class_($2,$4,$6,stringtable.add_string(curr_filename)); }
; ;
/* Feature list may be empty, but no empty features in list. */ /* Feature list may be empty, but no empty features in list. */
dummy_feature_list: /* empty */ feature_list: /* empty */
{ $$ = nil_Features(); } { $$ = nil_Features(); }
| feature ';'
{ $$ = single_Features($1); }
| feature_list feature ';'
{ $$ = append_Classes($1, single_Features($2)); }
;
feature : OBJECTID ':' TYPEID
/* Use no expr where optional expression omitted*/
{ $$ = attr($1, $3, no_expr()); }
| OBJECTID ':' TYPEID ASSIGN expression
{ $$ = attr($1, $3, $5); }
| OBJECTID '(' formal_list ')' ':' TYPEID '{' expression '}'
{ $$ = method($1, $3, $6, $8); }
;
formal_list : /* empty */
{ $$ = nil_Formals(); }
| formal
{ $$ = single_Formals($1); }
| formal_list ',' formal /* a little different from classlist */
{ $$ = append_Formals($1, single_Formals($3)); }
;
formal : OBJECTID ':' TYPEID
{ $$ = formal($1, $3); }
;
expression_list_comma : /* TODO Perhaps empty expr_list should not be valid? */
{ $$ = nil_Expressions(); }
| expression
{ $$ = single_Expressions($1); }
| expression_list_comma ',' expression
{ $$ = append_Expressions($1, single_Expressions($3)); }
;
expression_list_colon : /* TODO Perhaps empty expr_list should not be valid? */
{ $$ = nil_Expressions(); }
| expression ';'
{ $$ = single_Expressions($1); }
| expression_list_colon expression ';'
{ $$ = append_Expressions($1, single_Expressions($2)); }
;
expression : OBJECTID ASSIGN expression
{ $$ = assign($1, $3); }
/* expr[@TYPE].ID([expr[[,expr]]*]) */
| expression '.' OBJECTID '(' expression_list_comma ')'
{ $$ = dispatch($1, $3, $5); }
/* Only in the case of @TYPE, we use static dispatch*/
| expression '@' TYPEID '.' OBJECTID '(' expression_list_comma ')'
{ $$ = static_dispatch($1, $3, $5, $7); }
/* Actually, `ID( [ expr [[, expr]] ])` is self omitted, so add it in parsing */
| OBJECTID '(' expression_list_comma ')'
{ $$ = dispatch(object(idtable.add_string("self")), $1, $3); }
| IF expression THEN expression ELSE expression FI
{ $$ = cond($2, $4, $6); }
| WHILE expression LOOP expression POOL
{ $$ = loop($2, $4); }
| '{' expression_list_colon '}'
{ $$ = block($2); }
/* TODO let expr */
/* [manual-P21, tour-section6.5]
* The let constructor only allows one identifier.
* When parsing a let with multiple idents, it should be transformed into nested lets
*/
| LET nested_let
{ $$ = $2; }
| CASE expression OF case_list ESAC
{ $$ = typcase($2, $4); }
| NEW TYPEID
{ $$ = new_($2); }
| ISVOID expression
{ $$ = isvoid($1); }
/* the rules below need precedence specification */
| expression '+' expression
{ $$ = plus($1, $3); }
| expression '-' expression
{ $$ = sub($1, $3); }
| expression '*' expression
{ $$ = mul($1, $3); }
| expression '/' expression
{ $$ = divide($1, $3); }
| '~' expression
{ $$ = beg($2); }
| expression '<' expression
{ $$ = lt($1, $3); }
| expression LE expression
{ $$ = leq($1, $3); }
| expression '=' expression
{ $$ = eq($1, $3); }
| NOT expression
{ $$ = comp($2); }
| '(' expression ')'
{ $$ = $2; }
| OBJECTID
{ $$ = object($1); }
| INT_CONST
{ $$ = int_const($1); }
| STR_CONST
{ $$ = string_const($1); }
| BOOL_CONST
{ $$ = bool_const($1); }
;
case_list : case ';'
{ $$ = single_Cases($1); }
| case_list case ';'
{ $$ = append_Casess($1, single_Cases($2)); }
;
case : OBJECTID ':' TYPEID DARROW expression
{ $$ = branch($1, $3, $5); }
;
nested_let: OBJECTID ':' TYPEID ',' nested_let
{ $$ = let($1, $3, no_expr(), $5); }
| OBJECTID ':' TYPEID ASSIGN expression ',' nested_let
{ $$ = let($1, $3, $5, $7); }
| nested_let OBJECTID ':' TYPEID IN expression
{ $$ = let($2, $4, no_expr(), $6); }
| nested_let OBJECTID ':' TYPEID ASSIGN expression IN expression
{ $$ = let($2, $4, $6, $8); }
/* end of grammar */ /* end of grammar */
%% %%