buggy cool.y
This commit is contained in:
parent
ae7236fe58
commit
4db0884baa
@ -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 */
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user