exparse.y 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293
  1. /*************************************************************************
  2. * Copyright (c) 2011 AT&T Intellectual Property
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * https://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: Details at https://graphviz.org
  9. *************************************************************************/
  10. %require "3.0"
  11. /* By default, Bison emits a parser using symbols prefixed with "yy". Graphviz
  12. * contains multiple Bison-generated parsers, so we alter this prefix to avoid
  13. * symbol clashes.
  14. */
  15. %define api.prefix {ex_}
  16. %{
  17. /*
  18. * Glenn Fowler
  19. * AT&T Research
  20. *
  21. * expression library grammar and compiler
  22. */
  23. #include <assert.h>
  24. #include <cgraph/gv_ctype.h>
  25. #include <expr/exop.h>
  26. #include <stdbool.h>
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <ast/ast.h>
  31. #include <util/streq.h>
  32. %}
  33. %union
  34. {
  35. struct Exnode_s*expr;
  36. double floating;
  37. struct Exref_s* reference;
  38. struct Exid_s* id;
  39. long long integer;
  40. int op;
  41. char* string;
  42. }
  43. %start program
  44. %token MINTOKEN
  45. %token INTEGER
  46. %token UNSIGNED
  47. %token CHARACTER
  48. %token FLOATING
  49. %token STRING
  50. %token VOIDTYPE
  51. %token ADDRESS
  52. %token ARRAY
  53. %token BREAK
  54. %token CALL
  55. %token CASE
  56. %token CONSTANT
  57. %token CONTINUE
  58. %token DECLARE
  59. %token DEFAULT
  60. %token DYNAMIC
  61. %token ELSE
  62. %token EXIT
  63. %token FOR
  64. %token FUNCTION
  65. %token GSUB
  66. %token ITERATE
  67. %token ITERATOR
  68. %token ID
  69. %token IF
  70. %token LABEL
  71. %token MEMBER
  72. %token NAME
  73. %token POS
  74. %token PRAGMA
  75. %token PRE
  76. %token PRINT
  77. %token PRINTF
  78. %token PROCEDURE
  79. %token QUERY
  80. %token RAND
  81. %token RETURN
  82. %token SCANF
  83. %token SPLIT
  84. %token SPRINTF
  85. %token SRAND
  86. %token SSCANF
  87. %token SUB
  88. %token SUBSTR
  89. %token SWITCH
  90. %token TOKENS
  91. %token UNSET
  92. %token WHILE
  93. %token F2I
  94. %token F2S
  95. %token I2F
  96. %token I2S
  97. %token S2B
  98. %token S2F
  99. %token S2I
  100. %token F2X
  101. %token I2X
  102. %token S2X
  103. %token X2F
  104. %token X2I
  105. %token X2S
  106. %token X2X
  107. %token XPRINT
  108. %left <op> ','
  109. %right <op> '='
  110. %right <op> '?' ':'
  111. %left <op> OR
  112. %left <op> AND
  113. %left <op> '|'
  114. %left <op> '^'
  115. %left <op> '&'
  116. %binary <op> EQ NE
  117. %binary <op> '<' '>' LE GE
  118. %left <op> LSH RSH
  119. %left <op> '+' '-' IN_OP
  120. %left <op> '*' '/' '%'
  121. %right <op> '!' '~' '#' UNARY
  122. %right <op> INC DEC
  123. %right <op> CAST
  124. %left <op> '('
  125. %type <expr> statement statement_list arg_list
  126. %type <expr> else_opt expr_opt expr
  127. %type <expr> args variable assign
  128. %type <expr> dcl_list dcl_item index
  129. %type <expr> initialize switch_item constant
  130. %type <expr> formals formal_list formal_item
  131. %type <reference> members
  132. %type <id> ID LABEL NAME
  133. %type <id> CONSTANT ARRAY FUNCTION DECLARE
  134. %type <id> EXIT PRINT PRINTF QUERY
  135. %type <id> RAND SRAND
  136. %type <id> SPRINTF PROCEDURE name dcl_name
  137. %type <id> GSUB SUB SUBSTR
  138. %type <id> SPLIT TOKENS splitop
  139. %type <id> IF WHILE FOR ITERATOR
  140. %type <id> BREAK CONTINUE print member
  141. %type <id> RETURN DYNAMIC SWITCH UNSET
  142. %type <id> SCANF SSCANF scan
  143. %type <floating> FLOATING
  144. %type <integer> INTEGER UNSIGNED array
  145. %type <string> STRING
  146. %token MAXTOKEN
  147. /* ask Bison to generate a table, yytname, containing string representations
  148. * of all the above tokens
  149. */
  150. %token-table
  151. %{
  152. #include <expr/exgram.h>
  153. void ex_error(const char *message);
  154. %}
  155. %%
  156. program : statement_list action_list
  157. {
  158. if ($1) {
  159. if (expr.program->main.value)
  160. exfreenode(expr.program, expr.program->main.value);
  161. if ($1->op == S2B)
  162. {
  163. Exnode_t* x;
  164. x = $1;
  165. $1 = x->data.operand.left;
  166. x->data.operand.left = 0;
  167. exfreenode(expr.program, x);
  168. }
  169. expr.program->main.lex = PROCEDURE;
  170. expr.program->main.value = exnewnode(expr.program, PROCEDURE, true, $1->type, NULL, $1);
  171. }
  172. }
  173. ;
  174. action_list : /* empty */
  175. | action_list action
  176. ;
  177. action : LABEL ':' {
  178. if (expr.procedure)
  179. exerror("no nested function definitions");
  180. $1->lex = PROCEDURE;
  181. expr.procedure = $1->value = exnewnode(expr.program, PROCEDURE, true, $1->type, NULL, NULL);
  182. expr.procedure->type = INTEGER;
  183. static Dtdisc_t disc = {.key = offsetof(Exid_t, name)};
  184. if (expr.assigned && !streq($1->name, "begin"))
  185. {
  186. if (!(expr.procedure->data.procedure.frame = dtopen(&disc, Dtset)) ||
  187. !dtview(expr.procedure->data.procedure.frame, expr.program->symbols))
  188. exnospace();
  189. expr.program->symbols = expr.program->frame = expr.procedure->data.procedure.frame;
  190. }
  191. } statement_list
  192. {
  193. expr.procedure = 0;
  194. if (expr.program->frame)
  195. {
  196. expr.program->symbols = expr.program->frame->view;
  197. dtview(expr.program->frame, NULL);
  198. expr.program->frame = 0;
  199. }
  200. if ($4 && $4->op == S2B)
  201. {
  202. Exnode_t* x;
  203. x = $4;
  204. $4 = x->data.operand.left;
  205. x->data.operand.left = 0;
  206. exfreenode(expr.program, x);
  207. }
  208. $1->value->data.operand.right = excast(expr.program, $4, $1->type, NULL, 0);
  209. }
  210. ;
  211. statement_list : /* empty */
  212. {
  213. $$ = 0;
  214. }
  215. | statement_list statement
  216. {
  217. if (!$1)
  218. $$ = $2;
  219. else if (!$2)
  220. $$ = $1;
  221. else if ($1->op == CONSTANT)
  222. {
  223. exfreenode(expr.program, $1);
  224. $$ = $2;
  225. }
  226. else $$ = exnewnode(expr.program, ';', true, $2->type, $1, $2);
  227. }
  228. ;
  229. statement : '{' statement_list '}'
  230. {
  231. $$ = $2;
  232. }
  233. | expr_opt ';'
  234. {
  235. $$ = ($1 && $1->type == STRING) ? exnewnode(expr.program, S2B, true, INTEGER, $1, NULL) : $1;
  236. }
  237. | DECLARE {expr.declare = $1->type;} dcl_list ';'
  238. {
  239. $$ = $3;
  240. expr.declare = 0;
  241. }
  242. | IF '(' expr ')' statement else_opt
  243. {
  244. if (exisAssign ($3))
  245. exwarn ("assignment used as boolean in if statement");
  246. if ($3->type == STRING)
  247. $3 = exnewnode(expr.program, S2B, true, INTEGER, $3, NULL);
  248. else if (!INTEGRAL($3->type))
  249. $3 = excast(expr.program, $3, INTEGER, NULL, 0);
  250. $$ = exnewnode(expr.program, $1->index, true, INTEGER, $3, exnewnode(expr.program, ':', true, $5 ? $5->type : 0, $5, $6));
  251. }
  252. | FOR '(' variable ')' statement
  253. {
  254. $$ = exnewnode(expr.program, ITERATE, false, INTEGER, NULL, NULL);
  255. $$->data.generate.array = $3;
  256. if (!$3->data.variable.index || $3->data.variable.index->op != DYNAMIC)
  257. exerror("simple index variable expected");
  258. $$->data.generate.index = $3->data.variable.index->data.variable.symbol;
  259. if ($3->op == ID && $$->data.generate.index->type != INTEGER)
  260. exerror("integer index variable expected");
  261. exfreenode(expr.program, $3->data.variable.index);
  262. $3->data.variable.index = 0;
  263. $$->data.generate.statement = $5;
  264. }
  265. | FOR '(' expr_opt ';' expr_opt ';' expr_opt ')' statement
  266. {
  267. if (!$5)
  268. {
  269. $5 = exnewnode(expr.program, CONSTANT, false, INTEGER, NULL, NULL);
  270. $5->data.constant.value.integer = 1;
  271. }
  272. else if ($5->type == STRING)
  273. $5 = exnewnode(expr.program, S2B, true, INTEGER, $5, NULL);
  274. else if (!INTEGRAL($5->type))
  275. $5 = excast(expr.program, $5, INTEGER, NULL, 0);
  276. $$ = exnewnode(expr.program, $1->index, true, INTEGER, $5, exnewnode(expr.program, ';', 1, 0, $7, $9));
  277. if ($3)
  278. $$ = exnewnode(expr.program, ';', true, INTEGER, $3, $$);
  279. }
  280. | ITERATOR '(' variable ')' statement
  281. {
  282. $$ = exnewnode(expr.program, ITERATOR, false, INTEGER, NULL, NULL);
  283. $$->data.generate.array = $3;
  284. if (!$3->data.variable.index || $3->data.variable.index->op != DYNAMIC)
  285. exerror("simple index variable expected");
  286. $$->data.generate.index = $3->data.variable.index->data.variable.symbol;
  287. if ($3->op == ID && $$->data.generate.index->type != INTEGER)
  288. exerror("integer index variable expected");
  289. exfreenode(expr.program, $3->data.variable.index);
  290. $3->data.variable.index = 0;
  291. $$->data.generate.statement = $5;
  292. }
  293. | UNSET '(' DYNAMIC ')'
  294. {
  295. if ($3->local == NULL)
  296. exerror("cannot apply unset to non-array %s", $3->name);
  297. $$ = exnewnode(expr.program, UNSET, false, INTEGER, NULL, NULL);
  298. $$->data.variable.symbol = $3;
  299. $$->data.variable.index = NULL;
  300. }
  301. | UNSET '(' DYNAMIC ',' expr ')'
  302. {
  303. if ($3->local == NULL)
  304. exerror("cannot apply unset to non-array %s", $3->name);
  305. if (($3->index_type > 0) && ($5->type != $3->index_type))
  306. exerror("%s indices must have type %s, not %s",
  307. $3->name, extypename(expr.program, $3->index_type),extypename(expr.program, $5->type));
  308. $$ = exnewnode(expr.program, UNSET, false, INTEGER, NULL, NULL);
  309. $$->data.variable.symbol = $3;
  310. $$->data.variable.index = $5;
  311. }
  312. | WHILE '(' expr ')' statement
  313. {
  314. if (exisAssign ($3))
  315. exwarn ("assignment used as boolean in while statement");
  316. if ($3->type == STRING)
  317. $3 = exnewnode(expr.program, S2B, true, INTEGER, $3, NULL);
  318. else if (!INTEGRAL($3->type))
  319. $3 = excast(expr.program, $3, INTEGER, NULL, 0);
  320. $$ = exnewnode(expr.program, $1->index, true, INTEGER, $3, exnewnode(expr.program, ';', true, 0, NULL, $5));
  321. }
  322. | SWITCH '(' expr {expr.declare=$3->type;} ')' '{' switch_list '}'
  323. {
  324. Switch_t* sw = expr.swstate;
  325. $$ = exnewnode(expr.program, $1->index, true, INTEGER, $3, exnewnode(expr.program, DEFAULT, true, 0, sw->defcase, sw->firstcase));
  326. expr.swstate = expr.swstate->prev;
  327. free(sw->base);
  328. if (sw != &swstate)
  329. free(sw);
  330. expr.declare = 0;
  331. }
  332. | BREAK expr_opt ';'
  333. {
  334. loopop:
  335. if (!$2)
  336. {
  337. $2 = exnewnode(expr.program, CONSTANT, false, INTEGER, NULL, NULL);
  338. $2->data.constant.value.integer = 1;
  339. }
  340. else if (!INTEGRAL($2->type))
  341. $2 = excast(expr.program, $2, INTEGER, NULL, 0);
  342. $$ = exnewnode(expr.program, $1->index, true, INTEGER, $2, NULL);
  343. }
  344. | CONTINUE expr_opt ';'
  345. {
  346. goto loopop;
  347. }
  348. | RETURN expr_opt ';'
  349. {
  350. if ($2)
  351. {
  352. if (expr.procedure && !expr.procedure->type)
  353. exerror("return in void function");
  354. $2 = excast(expr.program, $2, expr.procedure ? expr.procedure->type : INTEGER, NULL, 0);
  355. }
  356. $$ = exnewnode(expr.program, RETURN, true, $2 ? $2->type : 0, $2, NULL);
  357. }
  358. ;
  359. switch_list : /* empty */
  360. {
  361. Switch_t* sw;
  362. if (expr.swstate)
  363. {
  364. if (!(sw = calloc(1, sizeof(Switch_t))))
  365. {
  366. exnospace();
  367. sw = &swstate;
  368. }
  369. sw->prev = expr.swstate;
  370. }
  371. else
  372. sw = &swstate;
  373. expr.swstate = sw;
  374. sw->type = expr.declare;
  375. sw->firstcase = 0;
  376. sw->lastcase = 0;
  377. sw->defcase = 0;
  378. sw->def = 0;
  379. size_t n = 8;
  380. if (!(sw->base = calloc(n, sizeof(Extype_t*))))
  381. {
  382. exnospace();
  383. n = 0;
  384. }
  385. sw->cur = sw->base;
  386. sw->last = sw->base + n;
  387. }
  388. | switch_list switch_item
  389. ;
  390. switch_item : case_list statement_list
  391. {
  392. Switch_t* sw = expr.swstate;
  393. $$ = exnewnode(expr.program, CASE, true, 0, $2, NULL);
  394. if (sw->cur > sw->base)
  395. {
  396. if (sw->lastcase)
  397. sw->lastcase->data.select.next = $$;
  398. else
  399. sw->firstcase = $$;
  400. sw->lastcase = $$;
  401. size_t n = (size_t)(sw->cur - sw->base);
  402. sw->cur = sw->base;
  403. $$->data.select.constant = exalloc(expr.program, (n + 1) * sizeof(Extype_t*));
  404. memcpy($$->data.select.constant, sw->base, n * sizeof(Extype_t*));
  405. $$->data.select.constant[n] = 0;
  406. }
  407. else
  408. $$->data.select.constant = 0;
  409. if (sw->def)
  410. {
  411. sw->def = 0;
  412. if (sw->defcase)
  413. exerror("duplicate default in switch");
  414. else
  415. sw->defcase = $2;
  416. }
  417. }
  418. ;
  419. case_list : case_item
  420. | case_list case_item
  421. ;
  422. case_item : CASE constant ':'
  423. {
  424. if (expr.swstate->cur >= expr.swstate->last)
  425. {
  426. size_t n = (size_t)(expr.swstate->cur - expr.swstate->base);
  427. if (!(expr.swstate->base = realloc(expr.swstate->base, sizeof(Extype_t*) * 2 * n)))
  428. {
  429. exerror("too many case labels for switch");
  430. n = 0;
  431. }
  432. expr.swstate->cur = expr.swstate->base + n;
  433. expr.swstate->last = expr.swstate->base + 2 * n;
  434. }
  435. if (expr.swstate->cur)
  436. {
  437. $2 = excast(expr.program, $2, expr.swstate->type, NULL, 0);
  438. *expr.swstate->cur++ = &($2->data.constant.value);
  439. }
  440. }
  441. | DEFAULT ':'
  442. {
  443. expr.swstate->def = 1;
  444. }
  445. ;
  446. dcl_list : dcl_item
  447. | dcl_list ',' dcl_item
  448. {
  449. if ($3)
  450. $$ = $1 ? exnewnode(expr.program, ',', true, $3->type, $1, $3) : $3;
  451. }
  452. ;
  453. dcl_item : dcl_name {checkName ($1); expr.id=$1;} array initialize
  454. {
  455. $$ = 0;
  456. if (!$1->type || expr.declare)
  457. $1->type = expr.declare;
  458. if ($4 && $4->op == PROCEDURE)
  459. {
  460. $1->lex = PROCEDURE;
  461. $1->type = $4->type;
  462. $1->value = $4;
  463. }
  464. else
  465. {
  466. if ($1->type == 0) {
  467. exerror("%s: a variable cannot be void typed", $1->name);
  468. }
  469. $1->lex = DYNAMIC;
  470. $1->value = exnewnode(expr.program, 0, false, 0, NULL, NULL);
  471. if ($3 && $1->local == NULL)
  472. {
  473. static Dtdisc_t disc_key = {
  474. .key = offsetof(Exassoc_t, key),
  475. .size = sizeof(Extype_t),
  476. .comparf = cmpKey,
  477. };
  478. static Dtdisc_t disc_name = {.key = offsetof(Exassoc_t, name)};
  479. Dtdisc_t *const disc = $3 == INTEGER ? &disc_key : &disc_name;
  480. if (!($1->local = dtopen(disc, Dtoset)))
  481. exerror("%s: cannot initialize associative array", $1->name);
  482. $1->index_type = $3; /* -1 indicates no typechecking */
  483. }
  484. if ($4)
  485. {
  486. if ($4->type != $1->type)
  487. {
  488. $4->type = $1->type;
  489. $4->data.operand.right = excast(expr.program, $4->data.operand.right, $1->type, NULL, 0);
  490. }
  491. $4->data.operand.left = exnewnode(expr.program, DYNAMIC, false, $1->type, NULL, NULL);
  492. $4->data.operand.left->data.variable.symbol = $1;
  493. $$ = $4;
  494. }
  495. else if (!$3)
  496. $1->value->data.value = exzero($1->type);
  497. }
  498. }
  499. ;
  500. dcl_name : NAME
  501. | DYNAMIC
  502. | ID
  503. | FUNCTION
  504. ;
  505. name : NAME
  506. | DYNAMIC
  507. ;
  508. else_opt : /* empty */
  509. {
  510. $$ = 0;
  511. }
  512. | ELSE statement
  513. {
  514. $$ = $2;
  515. }
  516. ;
  517. expr_opt : /* empty */
  518. {
  519. $$ = 0;
  520. }
  521. | expr
  522. ;
  523. expr : '(' expr ')'
  524. {
  525. $$ = $2;
  526. }
  527. | '(' DECLARE ')' expr %prec CAST
  528. {
  529. $$ = ($4->type == $2->type) ? $4 : excast(expr.program, $4, $2->type, NULL, 0);
  530. }
  531. | expr '<' expr
  532. {
  533. long rel;
  534. relational:
  535. rel = INTEGER;
  536. goto coerce;
  537. binary:
  538. rel = 0;
  539. coerce:
  540. if (!$1->type)
  541. {
  542. if (!$3->type)
  543. $1->type = $3->type = rel ? STRING : INTEGER;
  544. else
  545. $1->type = $3->type;
  546. }
  547. else if (!$3->type)
  548. $3->type = $1->type;
  549. if ($1->type != $3->type)
  550. {
  551. if ($1->type == STRING)
  552. $1 = excast(expr.program, $1, $3->type, $3, 0);
  553. else if ($3->type == STRING)
  554. $3 = excast(expr.program, $3, $1->type, $1, 0);
  555. else if ($1->type == FLOATING)
  556. $3 = excast(expr.program, $3, FLOATING, $1, 0);
  557. else if ($3->type == FLOATING)
  558. $1 = excast(expr.program, $1, FLOATING, $3, 0);
  559. }
  560. if (!rel)
  561. rel = ($1->type == STRING) ? STRING : (($1->type == UNSIGNED) ? UNSIGNED : $3->type);
  562. $$ = exnewnode(expr.program, $2, true, rel, $1, $3);
  563. if (!expr.program->errors && $1->op == CONSTANT && $3->op == CONSTANT)
  564. {
  565. $$->data.constant.value = exeval(expr.program, $$, NULL);
  566. /* If a constant string, re-allocate from program heap. This is because the
  567. * value was constructed from string operators, which create a value in the
  568. * temporary heap, which is cleared when exeval is called again.
  569. */
  570. if ($$->type == STRING) {
  571. $$->data.constant.value.string =
  572. vmstrdup(expr.program->vm, $$->data.constant.value.string);
  573. }
  574. $$->binary = false;
  575. $$->op = CONSTANT;
  576. exfreenode(expr.program, $1);
  577. exfreenode(expr.program, $3);
  578. }
  579. else if (!BUILTIN($1->type) || !BUILTIN($3->type)) {
  580. checkBinary(expr.program, $1, $$, $3);
  581. }
  582. }
  583. | expr '-' expr
  584. {
  585. goto binary;
  586. }
  587. | expr '*' expr
  588. {
  589. goto binary;
  590. }
  591. | expr '/' expr
  592. {
  593. goto binary;
  594. }
  595. | expr '%' expr
  596. {
  597. goto binary;
  598. }
  599. | expr LSH expr
  600. {
  601. goto binary;
  602. }
  603. | expr RSH expr
  604. {
  605. goto binary;
  606. }
  607. | expr '>' expr
  608. {
  609. goto relational;
  610. }
  611. | expr LE expr
  612. {
  613. goto relational;
  614. }
  615. | expr GE expr
  616. {
  617. goto relational;
  618. }
  619. | expr EQ expr
  620. {
  621. goto relational;
  622. }
  623. | expr NE expr
  624. {
  625. goto relational;
  626. }
  627. | expr '&' expr
  628. {
  629. goto binary;
  630. }
  631. | expr '|' expr
  632. {
  633. goto binary;
  634. }
  635. | expr '^' expr
  636. {
  637. goto binary;
  638. }
  639. | expr '+' expr
  640. {
  641. goto binary;
  642. }
  643. | expr AND expr
  644. {
  645. logical:
  646. if ($1->type == STRING)
  647. $1 = exnewnode(expr.program, S2B, true, INTEGER, $1, NULL);
  648. else if (!BUILTIN($1->type))
  649. $1 = excast(expr.program, $1, INTEGER, NULL, 0);
  650. if ($3->type == STRING)
  651. $3 = exnewnode(expr.program, S2B, true, INTEGER, $3, NULL);
  652. else if (!BUILTIN($3->type))
  653. $3 = excast(expr.program, $3, INTEGER, NULL, 0);
  654. goto binary;
  655. }
  656. | expr OR expr
  657. {
  658. goto logical;
  659. }
  660. | expr ',' expr
  661. {
  662. if ($1->op == CONSTANT)
  663. {
  664. exfreenode(expr.program, $1);
  665. $$ = $3;
  666. }
  667. else
  668. $$ = exnewnode(expr.program, ',', true, $3->type, $1, $3);
  669. }
  670. | expr '?' {expr.nolabel=1;} expr ':' {expr.nolabel=0;} expr
  671. {
  672. if (!$4->type)
  673. {
  674. if (!$7->type)
  675. $4->type = $7->type = INTEGER;
  676. else
  677. $4->type = $7->type;
  678. }
  679. else if (!$7->type)
  680. $7->type = $4->type;
  681. if ($1->type == STRING)
  682. $1 = exnewnode(expr.program, S2B, true, INTEGER, $1, NULL);
  683. else if (!INTEGRAL($1->type))
  684. $1 = excast(expr.program, $1, INTEGER, NULL, 0);
  685. if ($4->type != $7->type)
  686. {
  687. if ($4->type == STRING || $7->type == STRING)
  688. exerror("if statement string type mismatch");
  689. else if ($4->type == FLOATING)
  690. $7 = excast(expr.program, $7, FLOATING, NULL, 0);
  691. else if ($7->type == FLOATING)
  692. $4 = excast(expr.program, $4, FLOATING, NULL, 0);
  693. }
  694. if ($1->op == CONSTANT)
  695. {
  696. if ($1->data.constant.value.integer)
  697. {
  698. $$ = $4;
  699. exfreenode(expr.program, $7);
  700. }
  701. else
  702. {
  703. $$ = $7;
  704. exfreenode(expr.program, $4);
  705. }
  706. exfreenode(expr.program, $1);
  707. }
  708. else
  709. $$ = exnewnode(expr.program, '?', true, $4->type, $1, exnewnode(expr.program, ':', true, $4->type, $4, $7));
  710. }
  711. | '!' expr
  712. {
  713. iunary:
  714. if ($2->type == STRING)
  715. $2 = exnewnode(expr.program, S2B, true, INTEGER, $2, NULL);
  716. else if (!INTEGRAL($2->type))
  717. $2 = excast(expr.program, $2, INTEGER, NULL, 0);
  718. unary:
  719. $$ = exnewnode(expr.program, $1, true, $2->type == UNSIGNED ? INTEGER : $2->type, $2, NULL);
  720. if ($2->op == CONSTANT)
  721. {
  722. $$->data.constant.value = exeval(expr.program, $$, NULL);
  723. $$->binary = false;
  724. $$->op = CONSTANT;
  725. exfreenode(expr.program, $2);
  726. }
  727. else if (!BUILTIN($2->type)) {
  728. checkBinary(expr.program, $2, $$, 0);
  729. }
  730. }
  731. | '#' DYNAMIC
  732. {
  733. if ($2->local == NULL)
  734. exerror("cannot apply '#' operator to non-array %s", $2->name);
  735. $$ = exnewnode(expr.program, '#', false, INTEGER, NULL, NULL);
  736. $$->data.variable.symbol = $2;
  737. }
  738. | '~' expr
  739. {
  740. goto iunary;
  741. }
  742. | '-' expr %prec UNARY
  743. {
  744. goto unary;
  745. }
  746. | '+' expr %prec UNARY
  747. {
  748. $$ = $2;
  749. }
  750. | '&' variable %prec UNARY
  751. {
  752. $$ = exnewnode(expr.program, ADDRESS, false, T($2->type), $2, NULL);
  753. }
  754. | ARRAY '[' args ']'
  755. {
  756. $$ = exnewnode(expr.program, ARRAY, true, T($1->type), call(0, $1, $3), $3);
  757. }
  758. | FUNCTION '(' args ')'
  759. {
  760. $$ = exnewnode(expr.program, FUNCTION, true, T($1->type), call(0, $1, $3), $3);
  761. }
  762. | GSUB '(' args ')'
  763. {
  764. $$ = exnewsub (expr.program, $3, GSUB);
  765. }
  766. | SUB '(' args ')'
  767. {
  768. $$ = exnewsub (expr.program, $3, SUB);
  769. }
  770. | SUBSTR '(' args ')'
  771. {
  772. $$ = exnewsubstr (expr.program, $3);
  773. }
  774. | splitop '(' expr ',' DYNAMIC ')'
  775. {
  776. $$ = exnewsplit (expr.program, $1->index, $5, $3, NULL);
  777. }
  778. | splitop '(' expr ',' DYNAMIC ',' expr ')'
  779. {
  780. $$ = exnewsplit (expr.program, $1->index, $5, $3, $7);
  781. }
  782. | EXIT '(' expr ')'
  783. {
  784. if (!INTEGRAL($3->type))
  785. $3 = excast(expr.program, $3, INTEGER, NULL, 0);
  786. $$ = exnewnode(expr.program, EXIT, true, INTEGER, $3, NULL);
  787. }
  788. | RAND '(' ')'
  789. {
  790. $$ = exnewnode(expr.program, RAND, false, FLOATING, NULL, NULL);
  791. }
  792. | SRAND '(' ')'
  793. {
  794. $$ = exnewnode(expr.program, SRAND, false, INTEGER, NULL, NULL);
  795. }
  796. | SRAND '(' expr ')'
  797. {
  798. if (!INTEGRAL($3->type))
  799. $3 = excast(expr.program, $3, INTEGER, NULL, 0);
  800. $$ = exnewnode(expr.program, SRAND, true, INTEGER, $3, NULL);
  801. }
  802. | PROCEDURE '(' args ')'
  803. {
  804. $$ = exnewnode(expr.program, CALL, true, $1->type, NULL, $3);
  805. $$->data.call.procedure = $1;
  806. }
  807. | PRINT '(' args ')'
  808. {
  809. $$ = exprint(expr.program, $1, $3);
  810. }
  811. | print '(' args ')'
  812. {
  813. $$ = exnewnode(expr.program, $1->index, false, $1->type, NULL, NULL);
  814. if ($3 && $3->data.operand.left->type == INTEGER)
  815. {
  816. $$->data.print.descriptor = $3->data.operand.left;
  817. $3 = $3->data.operand.right;
  818. }
  819. else
  820. switch ($1->index)
  821. {
  822. case QUERY:
  823. $$->data.print.descriptor = exnewnode(expr.program, CONSTANT, false, INTEGER, NULL, NULL);
  824. $$->data.print.descriptor->data.constant.value.integer = 2;
  825. break;
  826. case PRINTF:
  827. $$->data.print.descriptor = exnewnode(expr.program, CONSTANT, false, INTEGER, NULL, NULL);
  828. $$->data.print.descriptor->data.constant.value.integer = 1;
  829. break;
  830. case SPRINTF:
  831. $$->data.print.descriptor = 0;
  832. break;
  833. }
  834. $$->data.print.args = preprint($3);
  835. }
  836. | scan '(' args ')'
  837. {
  838. Exnode_t* x;
  839. $$ = exnewnode(expr.program, $1->index, false, $1->type, NULL, NULL);
  840. if ($3 && $3->data.operand.left->type == INTEGER)
  841. {
  842. $$->data.scan.descriptor = $3->data.operand.left;
  843. $3 = $3->data.operand.right;
  844. }
  845. else
  846. switch ($1->index)
  847. {
  848. case SCANF:
  849. $$->data.scan.descriptor = 0;
  850. break;
  851. case SSCANF:
  852. if ($3 && $3->data.operand.left->type == STRING)
  853. {
  854. $$->data.scan.descriptor = $3->data.operand.left;
  855. $3 = $3->data.operand.right;
  856. }
  857. else
  858. exerror("%s: string argument expected", $1->name);
  859. break;
  860. }
  861. if (!$3 || !$3->data.operand.left || $3->data.operand.left->type != STRING)
  862. exerror("%s: format argument expected", $1->name);
  863. $$->data.scan.format = $3->data.operand.left;
  864. for (x = $$->data.scan.args = $3->data.operand.right; x; x = x->data.operand.right)
  865. {
  866. if (x->data.operand.left->op != ADDRESS)
  867. exerror("%s: address argument expected", $1->name);
  868. x->data.operand.left = x->data.operand.left->data.operand.left;
  869. }
  870. }
  871. | variable assign
  872. {
  873. if ($2)
  874. {
  875. if ($1->op == ID && !expr.program->disc->setf)
  876. exerror("%s: variable assignment not supported", $1->data.variable.symbol->name);
  877. else
  878. {
  879. if (!$1->type)
  880. $1->type = $2->type;
  881. else if ($2->type != $1->type)
  882. {
  883. $2->type = $1->type;
  884. $2->data.operand.right = excast(expr.program, $2->data.operand.right, $1->type, NULL, 0);
  885. }
  886. $2->data.operand.left = $1;
  887. $$ = $2;
  888. }
  889. }
  890. }
  891. | INC variable
  892. {
  893. pre:
  894. if ($2->type == STRING)
  895. exerror("++ and -- invalid for string variables");
  896. $$ = exnewnode(expr.program, $1, false, $2->type, $2, NULL);
  897. $$->subop = PRE;
  898. }
  899. | variable INC
  900. {
  901. pos:
  902. if ($1->type == STRING)
  903. exerror("++ and -- invalid for string variables");
  904. $$ = exnewnode(expr.program, $2, false, $1->type, $1, NULL);
  905. $$->subop = POS;
  906. }
  907. | expr IN_OP DYNAMIC
  908. {
  909. if ($3->local == NULL)
  910. exerror("cannot apply IN to non-array %s", $3->name);
  911. if (($3->index_type > 0) && ($1->type != $3->index_type))
  912. exerror("%s indices must have type %s, not %s",
  913. $3->name, extypename(expr.program, $3->index_type),extypename(expr.program, $1->type));
  914. $$ = exnewnode(expr.program, IN_OP, false, INTEGER, NULL, NULL);
  915. $$->data.variable.symbol = $3;
  916. $$->data.variable.index = $1;
  917. }
  918. | DEC variable
  919. {
  920. goto pre;
  921. }
  922. | variable DEC
  923. {
  924. goto pos;
  925. }
  926. | constant
  927. ;
  928. splitop : SPLIT
  929. | TOKENS
  930. ;
  931. constant : CONSTANT
  932. {
  933. $$ = exnewnode(expr.program, CONSTANT, false, $1->type, NULL, NULL);
  934. if (!expr.program->disc->reff)
  935. exerror("%s: identifier references not supported", $1->name);
  936. else
  937. $$->data.constant.value = expr.program->disc->reff(expr.program, $$, $1, NULL);
  938. }
  939. | FLOATING
  940. {
  941. $$ = exnewnode(expr.program, CONSTANT, false, FLOATING, NULL, NULL);
  942. $$->data.constant.value.floating = $1;
  943. }
  944. | INTEGER
  945. {
  946. $$ = exnewnode(expr.program, CONSTANT, false, INTEGER, NULL, NULL);
  947. $$->data.constant.value.integer = $1;
  948. }
  949. | STRING
  950. {
  951. $$ = exnewnode(expr.program, CONSTANT, false, STRING, NULL, NULL);
  952. $$->data.constant.value.string = $1;
  953. }
  954. | UNSIGNED
  955. {
  956. $$ = exnewnode(expr.program, CONSTANT, false, UNSIGNED, NULL, NULL);
  957. $$->data.constant.value.integer = $1;
  958. }
  959. ;
  960. print : PRINTF
  961. | QUERY
  962. | SPRINTF
  963. ;
  964. scan : SCANF
  965. | SSCANF
  966. ;
  967. variable : ID members
  968. {
  969. $$ = makeVar(expr.program, $1, 0, 0, $2);
  970. }
  971. | DYNAMIC index members
  972. {
  973. Exnode_t *n = exnewnode(expr.program, DYNAMIC, false, $1->type, NULL, NULL);
  974. n->data.variable.symbol = $1;
  975. n->data.variable.reference = 0;
  976. if (((n->data.variable.index = $2) == 0) != ($1->local == NULL))
  977. exerror("%s: is%s an array", $1->name, $1->local != NULL ? "" : " not");
  978. if ($1->local != NULL && ($1->index_type > 0)) {
  979. if ($2->type != $1->index_type)
  980. exerror("%s: indices must have type %s, not %s",
  981. $1->name, extypename(expr.program, $1->index_type),extypename(expr.program, $2->type));
  982. }
  983. if ($3) {
  984. n->data.variable.dyna = exnewnode(expr.program, 0, false, 0, NULL, NULL);
  985. $$ = makeVar(expr.program, $1, $2, n, $3);
  986. }
  987. else $$ = n;
  988. }
  989. | NAME
  990. {
  991. $$ = exnewnode(expr.program, ID, false, STRING, NULL, NULL);
  992. $$->data.variable.symbol = $1;
  993. $$->data.variable.reference = 0;
  994. $$->data.variable.index = 0;
  995. $$->data.variable.dyna = 0;
  996. if (!(expr.program->disc->flags & EX_UNDECLARED))
  997. exerror("unknown identifier");
  998. }
  999. ;
  1000. array : /* empty */
  1001. {
  1002. $$ = 0;
  1003. }
  1004. | '[' ']'
  1005. {
  1006. $$ = -1;
  1007. }
  1008. | '[' DECLARE ']'
  1009. {
  1010. /* If DECLARE is VOID, its type is 0, so this acts like
  1011. * the empty case.
  1012. */
  1013. if (INTEGRAL($2->type))
  1014. $$ = INTEGER;
  1015. else
  1016. $$ = $2->type;
  1017. }
  1018. ;
  1019. index : /* empty */
  1020. {
  1021. $$ = 0;
  1022. }
  1023. | '[' expr ']'
  1024. {
  1025. $$ = $2;
  1026. }
  1027. ;
  1028. args : /* empty */
  1029. {
  1030. $$ = 0;
  1031. }
  1032. | arg_list
  1033. {
  1034. $$ = $1->data.operand.left;
  1035. $1->data.operand.left = $1->data.operand.right = 0;
  1036. exfreenode(expr.program, $1);
  1037. }
  1038. ;
  1039. arg_list : expr %prec ','
  1040. {
  1041. $$ = exnewnode(expr.program, ',', true, 0, exnewnode(expr.program, ',', true, $1->type, $1, NULL), NULL);
  1042. $$->data.operand.right = $$->data.operand.left;
  1043. }
  1044. | arg_list ',' expr
  1045. {
  1046. $1->data.operand.right = $1->data.operand.right->data.operand.right = exnewnode(expr.program, ',', true, $1->type, $3, NULL);
  1047. }
  1048. ;
  1049. formals : /* empty */
  1050. {
  1051. $$ = 0;
  1052. }
  1053. | DECLARE
  1054. {
  1055. $$ = 0;
  1056. if ($1->type)
  1057. exerror("(void) expected");
  1058. }
  1059. | formal_list
  1060. ;
  1061. formal_list : formal_item
  1062. {
  1063. $$ = exnewnode(expr.program, ',', true, $1->type, $1, NULL);
  1064. }
  1065. | formal_list ',' formal_item
  1066. {
  1067. Exnode_t* x;
  1068. Exnode_t* y;
  1069. $$ = $1;
  1070. for (x = $1; (y = x->data.operand.right); x = y);
  1071. x->data.operand.right = exnewnode(expr.program, ',', true, $3->type, $3, NULL);
  1072. }
  1073. ;
  1074. formal_item : DECLARE {expr.declare=$1->type;} name
  1075. {
  1076. if ($1->type == 0) {
  1077. exerror("%s: parameters to functions cannot be void typed", $3->name);
  1078. }
  1079. $$ = exnewnode(expr.program, ID, false, $1->type, NULL, NULL);
  1080. $$->data.variable.symbol = $3;
  1081. $3->lex = DYNAMIC;
  1082. $3->type = $1->type;
  1083. $3->value = exnewnode(expr.program, 0, false, 0, NULL, NULL);
  1084. expr.procedure->data.procedure.arity++;
  1085. expr.declare = 0;
  1086. }
  1087. ;
  1088. members : /* empty */
  1089. {
  1090. $$ = expr.refs = 0;
  1091. }
  1092. | member
  1093. {
  1094. Exref_t* r;
  1095. r = ALLOCATE(expr.program, Exref_t);
  1096. *r = (Exref_t){0};
  1097. r->symbol = $1;
  1098. expr.refs = r;
  1099. r->next = 0;
  1100. r->index = 0;
  1101. $$ = expr.refs;
  1102. }
  1103. | '.' ID member
  1104. {
  1105. Exref_t* r;
  1106. Exref_t* l;
  1107. r = ALLOCATE(expr.program, Exref_t);
  1108. *r = (Exref_t){0};
  1109. r->symbol = $3;
  1110. r->index = 0;
  1111. r->next = 0;
  1112. l = ALLOCATE(expr.program, Exref_t);
  1113. *l = (Exref_t){0};
  1114. l->symbol = $2;
  1115. l->index = 0;
  1116. l->next = r;
  1117. expr.refs = l;
  1118. $$ = expr.refs;
  1119. }
  1120. ;
  1121. member : '.' ID
  1122. {
  1123. $$ = $2;
  1124. }
  1125. | '.' NAME
  1126. {
  1127. $$ = $2;
  1128. }
  1129. ;
  1130. assign : /* empty */
  1131. {
  1132. $$ = 0;
  1133. }
  1134. | '=' expr
  1135. {
  1136. $$ = exnewnode(expr.program, '=', true, $2->type, NULL, $2);
  1137. $$->subop = $1;
  1138. }
  1139. ;
  1140. initialize : assign
  1141. | '(' {
  1142. if (expr.procedure)
  1143. exerror("%s: nested function definitions not supported", expr.id->name);
  1144. expr.procedure = exnewnode(expr.program, PROCEDURE, true, expr.declare, NULL, NULL);
  1145. if (!streq(expr.id->name, "begin"))
  1146. {
  1147. static Dtdisc_t disc = {.key = offsetof(Exid_t, name)};
  1148. if (!(expr.procedure->data.procedure.frame = dtopen(&disc, Dtset)) || !dtview(expr.procedure->data.procedure.frame, expr.program->symbols))
  1149. exnospace();
  1150. expr.program->symbols = expr.program->frame = expr.procedure->data.procedure.frame;
  1151. }
  1152. expr.declare = 0;
  1153. } formals {
  1154. expr.id->lex = PROCEDURE;
  1155. expr.id->type = expr.procedure->type;
  1156. expr.declare = 0;
  1157. } ')' '{' statement_list '}'
  1158. {
  1159. $$ = expr.procedure;
  1160. expr.procedure = 0;
  1161. if (expr.program->frame)
  1162. {
  1163. expr.program->symbols = expr.program->frame->view;
  1164. dtview(expr.program->frame, NULL);
  1165. expr.program->frame = 0;
  1166. }
  1167. $$->data.operand.left = $3;
  1168. $$->data.operand.right = excast(expr.program, $7, $$->type, NULL, 0);
  1169. /*
  1170. * NOTE: procedure definition was slipped into the
  1171. * declaration initializer statement production,
  1172. * therefore requiring the statement terminator
  1173. */
  1174. exunlex(expr.program, ';');
  1175. }
  1176. ;
  1177. %%
  1178. const char *exop(size_t index) {
  1179. /* yytname is generated by the %token-table directive */
  1180. /* find the index of MINTOKEN */
  1181. size_t minid;
  1182. for (minid = 0; yytname[minid] != NULL; ++minid) {
  1183. if (strcmp(yytname[minid], "MINTOKEN") == 0) {
  1184. break;
  1185. }
  1186. }
  1187. assert(yytname[minid] != NULL
  1188. && "failed to find MINTOKEN; incorrect token list in exparse.y?");
  1189. /* find the requested token */
  1190. {
  1191. size_t i, j;
  1192. for (i = j = minid; yytname[i] != NULL; ++i) {
  1193. /* if this token is not a word, skip it */
  1194. {
  1195. size_t k;
  1196. for (k = 0; yytname[i][k] != '\0'; ++k) {
  1197. if (yytname[i][k] != '_' && !gv_isalnum(yytname[i][k])) {
  1198. break;
  1199. }
  1200. }
  1201. if (yytname[i][k] != '\0') {
  1202. continue;
  1203. }
  1204. }
  1205. if (j == index + minid) {
  1206. return yytname[i];
  1207. }
  1208. ++j;
  1209. }
  1210. }
  1211. /* failed to find the requested token */
  1212. return NULL;
  1213. }
  1214. void ex_error(const char *message) {
  1215. exerror("%s", message);
  1216. }
  1217. #include <expr/exgram.h>