syntax.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. /* ------------------------------------------------------------------------- */
  2. /* "syntax" : Syntax analyser and compiler */
  3. /* */
  4. /* Part of Inform 6.33 */
  5. /* copyright (c) Graham Nelson 1993 - 2014 */
  6. /* */
  7. /* ------------------------------------------------------------------------- */
  8. #include "header.h"
  9. static char *lexical_source;
  10. int no_syntax_lines; /* Syntax line count */
  11. static void begin_syntax_line(int statement_mode)
  12. { no_syntax_lines++;
  13. next_token_begins_syntax_line = TRUE;
  14. clear_expression_space();
  15. if (statement_mode)
  16. { statements.enabled = TRUE;
  17. conditions.enabled = TRUE;
  18. local_variables.enabled = TRUE;
  19. system_functions.enabled = TRUE;
  20. misc_keywords.enabled = FALSE;
  21. directive_keywords.enabled = FALSE;
  22. directives.enabled = FALSE;
  23. segment_markers.enabled = FALSE;
  24. opcode_names.enabled = FALSE;
  25. }
  26. else
  27. { directives.enabled = TRUE;
  28. segment_markers.enabled = TRUE;
  29. statements.enabled = FALSE;
  30. misc_keywords.enabled = FALSE;
  31. directive_keywords.enabled = FALSE;
  32. local_variables.enabled = FALSE;
  33. system_functions.enabled = FALSE;
  34. conditions.enabled = FALSE;
  35. opcode_names.enabled = FALSE;
  36. }
  37. sequence_point_follows = TRUE;
  38. if (debugfile_switch)
  39. { get_next_token();
  40. statement_debug_location = get_token_location();
  41. put_token_back();
  42. }
  43. }
  44. extern void panic_mode_error_recovery(void)
  45. {
  46. /* Consume tokens until the next semicolon (or end of file).
  47. This is typically called after a syntax error, in hopes of
  48. getting parsing back on track. */
  49. while ((token_type != EOF_TT)
  50. && ((token_type != SEP_TT)||(token_value != SEMICOLON_SEP)))
  51. get_next_token();
  52. }
  53. extern void get_next_token_with_directives(void)
  54. {
  55. /* A higher-level version of get_next_token(), which detects and
  56. obeys directives such as #ifdef/#ifnot/#endif. (The # sign is
  57. required in this case.)
  58. This is called while parsing a long construct, such as Class or
  59. Object, where we want to support internal #ifdefs. (Although
  60. function-parsing predates this and doesn't make use of it.)
  61. (Technically this permits *any* #-directive, which means you
  62. can define global variables or properties or what-have-you in
  63. the middle of an object. You can do that in the middle of an
  64. object, too. Don't. It's about as well-supported as Wile E.
  65. Coyote one beat before the plummet-lines kick in.) */
  66. int directives_save, segment_markers_save, statements_save;
  67. while (TRUE)
  68. {
  69. get_next_token();
  70. /* If the first token is not a '#', return it directly. */
  71. if ((token_type != SEP_TT) || (token_value != HASH_SEP))
  72. return;
  73. /* Save the lexer flags, and set up for directive parsing. */
  74. directives_save = directives.enabled;
  75. segment_markers_save = segment_markers.enabled;
  76. statements_save = statements.enabled;
  77. directives.enabled = TRUE;
  78. segment_markers.enabled = FALSE;
  79. statements.enabled = FALSE;
  80. conditions.enabled = FALSE;
  81. local_variables.enabled = FALSE;
  82. misc_keywords.enabled = FALSE;
  83. system_functions.enabled = FALSE;
  84. get_next_token();
  85. if ((token_type == SEP_TT) && (token_value == OPEN_SQUARE_SEP))
  86. { error("It is illegal to nest a routine inside an object using '#['");
  87. return;
  88. }
  89. if (token_type == DIRECTIVE_TT)
  90. parse_given_directive(TRUE);
  91. else
  92. { ebf_error("directive", token_text);
  93. return;
  94. }
  95. /* Restore all the lexer flags. (We are squashing several of them
  96. into a single save variable, which I think is safe because that's
  97. what CKnight did.)
  98. */
  99. directive_keywords.enabled = FALSE;
  100. directives.enabled = directives_save;
  101. segment_markers.enabled = segment_markers_save;
  102. statements.enabled =
  103. conditions.enabled =
  104. local_variables.enabled =
  105. misc_keywords.enabled =
  106. system_functions.enabled = statements_save;
  107. }
  108. }
  109. extern void parse_program(char *source)
  110. {
  111. lexical_source = source;
  112. while (parse_directive(FALSE)) ;
  113. }
  114. extern int parse_directive(int internal_flag)
  115. {
  116. /* Internal_flag is FALSE if the directive is encountered normally,
  117. TRUE if encountered with a # prefix inside a routine or object
  118. definition.
  119. Returns: TRUE if program continues, FALSE if end of file reached. */
  120. int routine_symbol, rep_symbol;
  121. int is_renamed;
  122. begin_syntax_line(FALSE);
  123. get_next_token();
  124. if (token_type == EOF_TT) return(FALSE);
  125. if ((token_type == SEP_TT) && (token_value == HASH_SEP))
  126. get_next_token();
  127. if ((token_type == SEP_TT) && (token_value == OPEN_SQUARE_SEP))
  128. { if (internal_flag)
  129. { error("It is illegal to nest routines using '#['");
  130. return(TRUE);
  131. }
  132. directives.enabled = FALSE;
  133. directive_keywords.enabled = FALSE;
  134. segment_markers.enabled = FALSE;
  135. /* The upcoming symbol is a definition; don't count it as a
  136. top-level reference *to* the function. */
  137. df_dont_note_global_symbols = TRUE;
  138. get_next_token();
  139. df_dont_note_global_symbols = FALSE;
  140. if ((token_type != SYMBOL_TT)
  141. || ((!(sflags[token_value] & UNKNOWN_SFLAG))
  142. && (!(sflags[token_value] & REPLACE_SFLAG))))
  143. { ebf_error("routine name", token_text);
  144. return(FALSE);
  145. }
  146. routine_symbol = token_value;
  147. rep_symbol = routine_symbol;
  148. is_renamed = find_symbol_replacement(&rep_symbol);
  149. if ((sflags[routine_symbol] & REPLACE_SFLAG)
  150. && !is_renamed && (is_systemfile()))
  151. { /* The function is definitely being replaced (system_file
  152. always loses priority in a replacement) but is not
  153. being renamed to something else. Skip its definition
  154. entirely. */
  155. dont_enter_into_symbol_table = TRUE;
  156. do
  157. { get_next_token();
  158. } while (!((token_type == EOF_TT)
  159. || ((token_type==SEP_TT)
  160. && (token_value==CLOSE_SQUARE_SEP))));
  161. dont_enter_into_symbol_table = FALSE;
  162. if (token_type == EOF_TT) return FALSE;
  163. }
  164. else
  165. { /* Parse the function definition and assign its symbol. */
  166. assign_symbol(routine_symbol,
  167. parse_routine(lexical_source, FALSE,
  168. (char *) symbs[routine_symbol], FALSE, routine_symbol),
  169. ROUTINE_T);
  170. slines[routine_symbol] = routine_starts_line;
  171. }
  172. if (is_renamed) {
  173. /* This function was subject to a "Replace X Y" directive.
  174. The first time we see a definition for symbol X, we
  175. copy it to Y -- that's the "original" form of the
  176. function. */
  177. if (svals[rep_symbol] == 0) {
  178. assign_symbol(rep_symbol, svals[routine_symbol], ROUTINE_T);
  179. }
  180. }
  181. get_next_token();
  182. if ((token_type != SEP_TT) || (token_value != SEMICOLON_SEP))
  183. { ebf_error("';' after ']'", token_text);
  184. put_token_back();
  185. }
  186. return TRUE;
  187. }
  188. if ((token_type == SYMBOL_TT) && (stypes[token_value] == CLASS_T))
  189. { if (internal_flag)
  190. { error("It is illegal to nest an object in a routine using '#classname'");
  191. return(TRUE);
  192. }
  193. sflags[token_value] |= USED_SFLAG;
  194. make_object(FALSE, NULL, -1, -1, svals[token_value]);
  195. return TRUE;
  196. }
  197. if (token_type != DIRECTIVE_TT)
  198. { /* If we're internal, we expect only a directive here. If
  199. we're top-level, the possibilities are broader. */
  200. if (internal_flag)
  201. ebf_error("directive", token_text);
  202. else
  203. ebf_error("directive, '[' or class name", token_text);
  204. panic_mode_error_recovery();
  205. return TRUE;
  206. }
  207. return !(parse_given_directive(internal_flag));
  208. }
  209. static int switch_sign(void)
  210. {
  211. if ((token_type == SEP_TT)&&(token_value == COLON_SEP)) return 1;
  212. if ((token_type == SEP_TT)&&(token_value == COMMA_SEP)) return 2;
  213. if ((token_type==MISC_KEYWORD_TT)&&(token_value==TO_MK)) return 3;
  214. return 0;
  215. }
  216. static assembly_operand spec_stack[32];
  217. static int spec_type[32];
  218. static void compile_alternatives_z(assembly_operand switch_value, int n,
  219. int stack_level, int label, int flag)
  220. { switch(n)
  221. { case 1:
  222. assemblez_2_branch(je_zc, switch_value,
  223. spec_stack[stack_level],
  224. label, flag); return;
  225. case 2:
  226. assemblez_3_branch(je_zc, switch_value,
  227. spec_stack[stack_level], spec_stack[stack_level+1],
  228. label, flag); return;
  229. case 3:
  230. assemblez_4_branch(je_zc, switch_value,
  231. spec_stack[stack_level], spec_stack[stack_level+1],
  232. spec_stack[stack_level+2],
  233. label, flag); return;
  234. }
  235. }
  236. static void compile_alternatives_g(assembly_operand switch_value, int n,
  237. int stack_level, int label, int flag)
  238. {
  239. int the_zc = (flag) ? jeq_gc : jne_gc;
  240. if (n == 1) {
  241. assembleg_2_branch(the_zc, switch_value,
  242. spec_stack[stack_level],
  243. label);
  244. }
  245. else {
  246. error("*** Cannot generate multi-equality tests in Glulx ***");
  247. }
  248. }
  249. static void compile_alternatives(assembly_operand switch_value, int n,
  250. int stack_level, int label, int flag)
  251. {
  252. if (!glulx_mode)
  253. compile_alternatives_z(switch_value, n, stack_level, label, flag);
  254. else
  255. compile_alternatives_g(switch_value, n, stack_level, label, flag);
  256. }
  257. static void parse_switch_spec(assembly_operand switch_value, int label,
  258. int action_switch)
  259. {
  260. int i, j, label_after = -1, spec_sp = 0;
  261. int max_equality_args = ((!glulx_mode) ? 3 : 1);
  262. sequence_point_follows = FALSE;
  263. do
  264. { if (spec_sp == 32)
  265. { error("At most 32 values can be given in a single 'switch' case");
  266. panic_mode_error_recovery();
  267. return;
  268. }
  269. if (action_switch)
  270. { get_next_token();
  271. spec_stack[spec_sp].type =
  272. ((!glulx_mode) ? LONG_CONSTANT_OT : CONSTANT_OT);
  273. spec_stack[spec_sp].value = 0;
  274. spec_stack[spec_sp].marker = 0;
  275. spec_stack[spec_sp] = action_of_name(token_text);
  276. if (spec_stack[spec_sp].value == -1)
  277. { spec_stack[spec_sp].value = 0;
  278. ebf_error("action (or fake action) name", token_text);
  279. }
  280. }
  281. else
  282. spec_stack[spec_sp] =
  283. code_generate(parse_expression(CONSTANT_CONTEXT), CONSTANT_CONTEXT, -1);
  284. misc_keywords.enabled = TRUE;
  285. get_next_token();
  286. misc_keywords.enabled = FALSE;
  287. spec_type[spec_sp++] = switch_sign();
  288. switch(spec_type[spec_sp-1])
  289. { case 0:
  290. if (action_switch)
  291. ebf_error("',' or ':'", token_text);
  292. else ebf_error("',', ':' or 'to'", token_text);
  293. panic_mode_error_recovery();
  294. return;
  295. case 1: goto GenSpecCode;
  296. case 3: if (label_after == -1) label_after = next_label++;
  297. }
  298. } while(TRUE);
  299. GenSpecCode:
  300. if ((spec_sp > max_equality_args) && (label_after == -1))
  301. label_after = next_label++;
  302. if (label_after == -1)
  303. { compile_alternatives(switch_value, spec_sp, 0, label, FALSE); return;
  304. }
  305. for (i=0; i<spec_sp;)
  306. {
  307. j=i; while ((j<spec_sp) && (spec_type[j] != 3)) j++;
  308. if (j > i)
  309. { if (j-i > max_equality_args) j=i+max_equality_args;
  310. if (j == spec_sp)
  311. compile_alternatives(switch_value, j-i, i, label, FALSE);
  312. else
  313. compile_alternatives(switch_value, j-i, i, label_after, TRUE);
  314. i=j;
  315. }
  316. else
  317. {
  318. if (!glulx_mode) {
  319. if (i == spec_sp - 2)
  320. { assemblez_2_branch(jl_zc, switch_value, spec_stack[i],
  321. label, TRUE);
  322. assemblez_2_branch(jg_zc, switch_value, spec_stack[i+1],
  323. label, TRUE);
  324. }
  325. else
  326. { assemblez_2_branch(jl_zc, switch_value, spec_stack[i],
  327. next_label, TRUE);
  328. assemblez_2_branch(jg_zc, switch_value, spec_stack[i+1],
  329. label_after, FALSE);
  330. assemble_label_no(next_label++);
  331. }
  332. }
  333. else {
  334. if (i == spec_sp - 2)
  335. { assembleg_2_branch(jlt_gc, switch_value, spec_stack[i],
  336. label);
  337. assembleg_2_branch(jgt_gc, switch_value, spec_stack[i+1],
  338. label);
  339. }
  340. else
  341. { assembleg_2_branch(jlt_gc, switch_value, spec_stack[i],
  342. next_label);
  343. assembleg_2_branch(jle_gc, switch_value, spec_stack[i+1],
  344. label_after);
  345. assemble_label_no(next_label++);
  346. }
  347. }
  348. i = i+2;
  349. }
  350. }
  351. assemble_label_no(label_after);
  352. }
  353. extern int32 parse_routine(char *source, int embedded_flag, char *name,
  354. int veneer_flag, int r_symbol)
  355. { int32 packed_address; int i; int debug_flag = FALSE;
  356. int switch_clause_made = FALSE, default_clause_made = FALSE,
  357. switch_label = 0;
  358. debug_location_beginning beginning_debug_location =
  359. get_token_location_beginning();
  360. /* (switch_label needs no initialisation here, but it prevents some
  361. compilers from issuing warnings) */
  362. if ((source != lexical_source) || (veneer_flag))
  363. { lexical_source = source;
  364. restart_lexer(lexical_source, name);
  365. }
  366. no_locals = 0;
  367. for (i=0;i<MAX_LOCAL_VARIABLES-1;i++) local_variables.keywords[i] = "";
  368. do
  369. { statements.enabled = TRUE;
  370. dont_enter_into_symbol_table = TRUE;
  371. get_next_token();
  372. dont_enter_into_symbol_table = FALSE;
  373. if ((token_type == SEP_TT) && (token_value == TIMES_SEP)
  374. && (no_locals == 0) && (!debug_flag))
  375. { debug_flag = TRUE; continue;
  376. }
  377. if (token_type != DQ_TT)
  378. { if ((token_type == SEP_TT)
  379. && (token_value == SEMICOLON_SEP)) break;
  380. ebf_error("local variable name or ';'", token_text);
  381. panic_mode_error_recovery();
  382. break;
  383. }
  384. if (no_locals == MAX_LOCAL_VARIABLES-1)
  385. { error_numbered("Too many local variables for a routine; max is",
  386. MAX_LOCAL_VARIABLES-1);
  387. panic_mode_error_recovery();
  388. break;
  389. }
  390. for (i=0;i<no_locals;i++)
  391. if (strcmpcis(token_text, local_variables.keywords[i])==0)
  392. error_named("Local variable defined twice:", token_text);
  393. local_variables.keywords[no_locals++] = token_text;
  394. } while(TRUE);
  395. construct_local_variable_tables();
  396. if ((trace_fns_setting==3)
  397. || ((trace_fns_setting==2) && (veneer_mode==FALSE))
  398. || ((trace_fns_setting==1) && (is_systemfile()==FALSE)))
  399. debug_flag = TRUE;
  400. if ((embedded_flag == FALSE) && (veneer_mode == FALSE) && debug_flag)
  401. sflags[r_symbol] |= STAR_SFLAG;
  402. packed_address = assemble_routine_header(no_locals, debug_flag,
  403. name, embedded_flag, r_symbol);
  404. do
  405. { begin_syntax_line(TRUE);
  406. get_next_token();
  407. if (token_type == EOF_TT)
  408. { ebf_error("']'", token_text);
  409. assemble_routine_end
  410. (embedded_flag,
  411. get_token_location_end(beginning_debug_location));
  412. put_token_back();
  413. break;
  414. }
  415. if ((token_type == SEP_TT)
  416. && (token_value == CLOSE_SQUARE_SEP))
  417. { if (switch_clause_made && (!default_clause_made))
  418. assemble_label_no(switch_label);
  419. directives.enabled = TRUE;
  420. sequence_point_follows = TRUE;
  421. get_next_token();
  422. assemble_routine_end
  423. (embedded_flag,
  424. get_token_location_end(beginning_debug_location));
  425. put_token_back();
  426. break;
  427. }
  428. if ((token_type == STATEMENT_TT) && (token_value == SDEFAULT_CODE))
  429. { if (default_clause_made)
  430. error("Multiple 'default' clauses defined in same 'switch'");
  431. default_clause_made = TRUE;
  432. if (switch_clause_made)
  433. { if (!execution_never_reaches_here)
  434. { sequence_point_follows = FALSE;
  435. if (!glulx_mode)
  436. assemblez_0((embedded_flag)?rfalse_zc:rtrue_zc);
  437. else
  438. assembleg_1(return_gc,
  439. ((embedded_flag)?zero_operand:one_operand));
  440. }
  441. assemble_label_no(switch_label);
  442. }
  443. switch_clause_made = TRUE;
  444. get_next_token();
  445. if ((token_type == SEP_TT) &&
  446. (token_value == COLON_SEP)) continue;
  447. ebf_error("':' after 'default'", token_text);
  448. panic_mode_error_recovery();
  449. continue;
  450. }
  451. /* Only check for the form of a case switch if the initial token
  452. isn't double-quoted text, as that would mean it was a print_ret
  453. statement: this is a mild ambiguity in the grammar.
  454. Action statements also cannot be cases. */
  455. if ((token_type != DQ_TT) && (token_type != SEP_TT))
  456. { get_next_token();
  457. if (switch_sign() > 0)
  458. { assembly_operand AO;
  459. if (default_clause_made)
  460. error("'default' must be the last 'switch' case");
  461. if (switch_clause_made)
  462. { if (!execution_never_reaches_here)
  463. { sequence_point_follows = FALSE;
  464. if (!glulx_mode)
  465. assemblez_0((embedded_flag)?rfalse_zc:rtrue_zc);
  466. else
  467. assembleg_1(return_gc,
  468. ((embedded_flag)?zero_operand:one_operand));
  469. }
  470. assemble_label_no(switch_label);
  471. }
  472. switch_label = next_label++;
  473. switch_clause_made = TRUE;
  474. put_token_back(); put_token_back();
  475. if (!glulx_mode) {
  476. AO.type = VARIABLE_OT; AO.value = 249; AO.marker = 0;
  477. }
  478. else {
  479. AO.type = GLOBALVAR_OT;
  480. AO.value = MAX_LOCAL_VARIABLES+6; /* sw__var */
  481. AO.marker = 0;
  482. }
  483. parse_switch_spec(AO, switch_label, TRUE);
  484. continue;
  485. }
  486. else
  487. { put_token_back(); put_token_back(); get_next_token();
  488. sequence_point_follows = TRUE;
  489. }
  490. }
  491. parse_statement(-1, -1);
  492. } while (TRUE);
  493. return packed_address;
  494. }
  495. extern void parse_code_block(int break_label, int continue_label,
  496. int switch_rule)
  497. { int switch_clause_made = FALSE, default_clause_made = FALSE, switch_label,
  498. unary_minus_flag;
  499. begin_syntax_line(TRUE);
  500. get_next_token();
  501. if (token_type == SEP_TT && token_value == OPEN_BRACE_SEP)
  502. { do
  503. { begin_syntax_line(TRUE);
  504. get_next_token();
  505. if (token_type == SEP_TT && token_value == CLOSE_BRACE_SEP)
  506. { if (switch_clause_made && (!default_clause_made))
  507. assemble_label_no(switch_label);
  508. return;
  509. }
  510. if (token_type == EOF_TT)
  511. { ebf_error("'}'", token_text); return; }
  512. if (switch_rule != 0)
  513. {
  514. /* Within a 'switch' block */
  515. if ((token_type==STATEMENT_TT)&&(token_value==SDEFAULT_CODE))
  516. { if (default_clause_made)
  517. error("Multiple 'default' clauses defined in same 'switch'");
  518. default_clause_made = TRUE;
  519. if (switch_clause_made)
  520. { if (!execution_never_reaches_here)
  521. { sequence_point_follows = FALSE;
  522. assemble_jump(break_label);
  523. }
  524. assemble_label_no(switch_label);
  525. }
  526. switch_clause_made = TRUE;
  527. get_next_token();
  528. if ((token_type == SEP_TT) &&
  529. (token_value == COLON_SEP)) continue;
  530. ebf_error("':' after 'default'", token_text);
  531. panic_mode_error_recovery();
  532. continue;
  533. }
  534. /* Decide: is this an ordinary statement, or the start
  535. of a new case? */
  536. if (token_type == DQ_TT) goto NotASwitchCase;
  537. unary_minus_flag
  538. = ((token_type == SEP_TT)&&(token_value == MINUS_SEP));
  539. if (unary_minus_flag) get_next_token();
  540. /* Now read the token _after_ any possible constant:
  541. if that's a 'to', ',' or ':' then we have a case */
  542. misc_keywords.enabled = TRUE;
  543. get_next_token();
  544. misc_keywords.enabled = FALSE;
  545. if (switch_sign() > 0)
  546. { assembly_operand AO;
  547. if (default_clause_made)
  548. error("'default' must be the last 'switch' case");
  549. if (switch_clause_made)
  550. { if (!execution_never_reaches_here)
  551. { sequence_point_follows = FALSE;
  552. assemble_jump(break_label);
  553. }
  554. assemble_label_no(switch_label);
  555. }
  556. switch_label = next_label++;
  557. switch_clause_made = TRUE;
  558. put_token_back(); put_token_back();
  559. if (unary_minus_flag) put_token_back();
  560. AO = temp_var1;
  561. parse_switch_spec(AO, switch_label, FALSE);
  562. continue;
  563. }
  564. else
  565. { put_token_back(); put_token_back();
  566. if (unary_minus_flag) put_token_back();
  567. get_next_token();
  568. }
  569. }
  570. if ((switch_rule != 0) && (!switch_clause_made))
  571. ebf_error("switch value", token_text);
  572. NotASwitchCase:
  573. sequence_point_follows = TRUE;
  574. parse_statement(break_label, continue_label);
  575. }
  576. while(TRUE);
  577. }
  578. if (switch_rule != 0)
  579. ebf_error("braced code block after 'switch'", token_text);
  580. parse_statement(break_label, continue_label);
  581. return;
  582. }
  583. /* ========================================================================= */
  584. /* Data structure management routines */
  585. /* ------------------------------------------------------------------------- */
  586. extern void init_syntax_vars(void)
  587. {
  588. }
  589. extern void syntax_begin_pass(void)
  590. { no_syntax_lines = 0;
  591. }
  592. extern void syntax_allocate_arrays(void)
  593. {
  594. }
  595. extern void syntax_free_arrays(void)
  596. {
  597. }
  598. /* ========================================================================= */