972 |
| which says where to find `$0' with respect to the top of the | |
| which says where to find `$0' with respect to the top of the | |
973 |
| stack. It is not the same as the rule->length in the case of mid | |
| stack. It is not the same as the rule->length in the case of mid | |
974 |
| rule actions. | |
| rule actions. | |
|
| | |
|
|
| This routine is used for actions. | |
|
975 |
`------------------------------------------------------------------*/ |
`------------------------------------------------------------------*/ |
976 |
|
|
977 |
static void |
static void |
1167 |
grammar_symbol_append (sdummy); |
grammar_symbol_append (sdummy); |
1168 |
} |
} |
1169 |
|
|
1170 |
|
/* Set the precedence symbol of the current rule to PRECSYM. */ |
1171 |
|
|
1172 |
|
static void |
1173 |
|
grammar_current_rule_prec_set (symbol_t *precsym) |
1174 |
|
{ |
1175 |
|
if (current_rule->ruleprec) |
1176 |
|
complain (_("two @prec's in a row")); |
1177 |
|
current_rule->ruleprec = precsym; |
1178 |
|
} |
1179 |
|
|
1180 |
|
/* Check that the last rule (CURRENT_RULE) is properly defined. For |
1181 |
|
instance, there should be no type clash on the default action. */ |
1182 |
|
|
1183 |
|
static void |
1184 |
|
grammar_current_rule_check (void) |
1185 |
|
{ |
1186 |
|
symbol_t *lhs = current_rule->sym; |
1187 |
|
symbol_t *first_rhs = current_rule->next->sym; |
1188 |
|
|
1189 |
|
/* If there is an action, then there is nothing we can do: the user |
1190 |
|
is allowed to shoot in her foot. */ |
1191 |
|
if (current_rule->action) |
1192 |
|
return; |
1193 |
|
|
1194 |
|
/* If $$ is being set in default way, report if any type mismatch. |
1195 |
|
*/ |
1196 |
|
if (first_rhs) |
1197 |
|
{ |
1198 |
|
const char *lhs_type = lhs->type_name ? lhs->type_name : ""; |
1199 |
|
const char *rhs_type = first_rhs->type_name ? first_rhs->type_name : ""; |
1200 |
|
if (strcmp (lhs_type, rhs_type)) |
1201 |
|
complain (_("type clash (`%s' `%s') on default action"), |
1202 |
|
lhs_type, rhs_type); |
1203 |
|
} |
1204 |
|
/* Warn if there is no default for $$ but we need one. */ |
1205 |
|
else |
1206 |
|
{ |
1207 |
|
if (lhs->type_name) |
1208 |
|
complain (_("empty rule for typed nonterminal, and no action")); |
1209 |
|
} |
1210 |
|
} |
1211 |
|
|
1212 |
|
|
1213 |
static void |
static void |
1214 |
readgram (void) |
readgram (void) |
1224 |
int action_flag = 0; |
int action_flag = 0; |
1225 |
/* Number of symbols in rhs of this rule so far */ |
/* Number of symbols in rhs of this rule so far */ |
1226 |
int rulelength = 0; |
int rulelength = 0; |
|
int xactions = 0; /* JF for error checking */ |
|
|
symbol_t *first_rhs = 0; |
|
1227 |
|
|
1228 |
if (t == tok_identifier) |
if (t == tok_identifier) |
1229 |
{ |
{ |
1251 |
if (t == tok_prec) |
if (t == tok_prec) |
1252 |
{ |
{ |
1253 |
t = lex (); |
t = lex (); |
1254 |
current_rule->ruleprec = symval; |
grammar_current_rule_prec_set (symval); |
1255 |
t = lex (); |
t = lex (); |
1256 |
} |
} |
1257 |
|
|
1274 |
warn (_("previous rule lacks an ending `;'")); |
warn (_("previous rule lacks an ending `;'")); |
1275 |
break; |
break; |
1276 |
} |
} |
1277 |
|
/* Not followed by colon => process as part of this |
1278 |
if (!first_rhs) /* JF */ |
rule's rhs. */ |
|
first_rhs = symval; |
|
|
/* Not followed by colon => |
|
|
process as part of this rule's rhs. */ |
|
1279 |
} |
} |
1280 |
|
|
1281 |
/* If we just passed an action, that action was in the middle |
/* If we just passed an action, that action was in the middle |
1296 |
{ |
{ |
1297 |
parse_action (current_rule, rulelength); |
parse_action (current_rule, rulelength); |
1298 |
action_flag = 1; |
action_flag = 1; |
|
++xactions; /* JF */ |
|
1299 |
} |
} |
1300 |
++rulelength; |
++rulelength; |
1301 |
} /* end of read rhs of rule */ |
} /* end of read rhs of rule */ |
1305 |
|
|
1306 |
if (t == tok_prec) |
if (t == tok_prec) |
1307 |
{ |
{ |
|
complain (_("two @prec's in a row")); |
|
1308 |
t = lex (); |
t = lex (); |
1309 |
current_rule->ruleprec = symval; |
grammar_current_rule_prec_set (symval); |
1310 |
t = lex (); |
t = lex (); |
1311 |
} |
} |
1312 |
|
|
1313 |
if (t == tok_left_curly) |
if (t == tok_left_curly) |
1314 |
{ |
{ |
|
/* This case never occurs -wjh */ |
|
|
if (action_flag) |
|
|
complain (_("two actions at end of one rule")); |
|
1315 |
parse_action (current_rule, rulelength); |
parse_action (current_rule, rulelength); |
1316 |
action_flag = 1; |
action_flag = 1; |
|
++xactions; /* -wjh */ |
|
1317 |
t = lex (); |
t = lex (); |
1318 |
} |
} |
1319 |
/* If $$ is being set in default way, report if any type |
|
1320 |
mismatch. */ |
grammar_current_rule_check (); |
1321 |
else if (!xactions |
|
|
&& first_rhs && lhs->type_name != first_rhs->type_name) |
|
|
{ |
|
|
if (lhs->type_name == 0 |
|
|
|| first_rhs->type_name == 0 |
|
|
|| strcmp (lhs->type_name, first_rhs->type_name)) |
|
|
complain (_("type clash (`%s' `%s') on default action"), |
|
|
lhs->type_name ? lhs->type_name : "", |
|
|
first_rhs->type_name ? first_rhs->type_name : ""); |
|
|
} |
|
|
/* Warn if there is no default for $$ but we need one. */ |
|
|
else if (!xactions && !first_rhs && lhs->type_name != 0) |
|
|
complain (_("empty rule for typed nonterminal, and no action")); |
|
1322 |
if (t == tok_two_percents || t == tok_eof) |
if (t == tok_two_percents || t == tok_eof) |
1323 |
warn (_("previous rule lacks an ending `;'")); |
warn (_("previous rule lacks an ending `;'")); |
1324 |
if (t == tok_semicolon) |
if (t == tok_semicolon) |