home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / awk / awk320sr.zip / AWKYACC.Y < prev    next >
Text File  |  1991-04-28  |  23KB  |  1,087 lines

  1. %{
  2. /*
  3.  * Awk syntactical analyser and pseudo code generator
  4.  *
  5.  * Copyright (C) 1988, 1989, 1990, 1991 by Rob Duff
  6.  * All rights reserved
  7.  */
  8. #include <stddef.h>
  9. #include <alloc.h>
  10. #include <mem.h>
  11.  
  12. #include "awk.h"
  13. #include "awklex.h"
  14. %}
  15. %union
  16. {
  17.     int     ival;
  18.     double  dval;
  19.     char   *sptr;
  20.     FUNC   *uptr;
  21.     void   *vptr;
  22. }
  23.  
  24. %token T_EOF
  25. %token T_EOL
  26. %token T_BEGIN
  27. %token T_END
  28. %token T_IF
  29. %token T_ELSE
  30. %token T_FOR
  31. %token T_DO
  32. %token T_DONE
  33. %token T_WHILE
  34. %token T_BREAK
  35. %token T_CONTINUE
  36. %token T_FUNCTION
  37. %token T_RETURN
  38. %token T_NEXT
  39. %token T_EXIT
  40.  
  41. %token T_PRINT
  42. %token T_PRINTF
  43.  
  44. %token T_INDEX
  45. %token T_SRAND
  46. %token T_CLOSE
  47. %token T_SPLIT
  48. %token T_MATCH
  49. %token T_DELETE
  50. %token T_SUBSTR
  51. %token T_SPRINTF
  52.  
  53. %token T_GETLINE
  54.  
  55. %token <ival> T_SUB
  56. %token <vptr> T_USER
  57. %token <vptr> T_NAME
  58. %token <sptr> T_SCON
  59. %token <dval> T_DCON
  60. %token <ival> T_FUNC0
  61. %token <ival> T_FUNC1
  62. %token <ival> T_FUNC2
  63.  
  64. %right T_CREATE T_APPEND
  65. %right <ival> T_STORE
  66. %left '?' ':'
  67. %nonassoc T_LIOR
  68. %nonassoc T_LAND
  69. %nonassoc T_IN
  70. %nonassoc '~' T_NOMATCH
  71. %nonassoc <ival> T_RELOP '<' '>'
  72. %left T_CONCAT
  73. %left '+' '-'
  74. %left '*' '/'
  75. %right T_SIGN
  76. %right '!'
  77. %right '^'
  78. %left <ival> T_INCOP
  79. %right '$'
  80. %nonassoc T_GROUP
  81.  
  82. %type <ival> pattern_expression pattern_disjunction pattern_conjunction
  83. %type <ival> expression print_expression conditional print_conditional 
  84. %type <ival> print_disjunction disjunction conjunction print_conjunction 
  85. %type <ival> membership print_membership match print_match
  86. %type <ival> match_relation relation match_concatenation
  87. %type <ival> concatenation arithmetic term unary exponential factor
  88. %type <ival> optional_argument_list optional_expression
  89. %type <ival> optional_print_list expression_list print_expression_list
  90. %type <ival> field_zero_match regular_expression
  91. %type <uptr> declaration
  92. %type <vptr> body action pattern pattern_predicate
  93. %type <vptr> optional_parameter_list parameter_list
  94. %%
  95. pattern_action_list:
  96.     pattern_action_list eos pattern_action
  97. |   pattern_action
  98. ;
  99. pattern_action:
  100.     T_FUNCTION declaration body {
  101.         yydisplay = NULL;
  102.         $2->pcode = $3;
  103.     }
  104. |    T_BEGIN action {
  105.         if (beginend == NULL)
  106.             beginact = beginend = genact($2);
  107.         else
  108.             beginend = beginend->cnext = genact($2);
  109.     }
  110. |   T_END action {
  111.         if (endend == NULL)
  112.             endact = endend = genact($2);
  113.         else
  114.             endend = endend->cnext = genact($2);
  115.     }
  116. |   pattern action {
  117.         enroll($1, $2);
  118.     }
  119. |   pattern {
  120.         genfield(0);
  121.         lastop(C_PLUCK);
  122.         genfcon(0);
  123.         gencall(P_PRINT, 2);
  124.         genbyte(C_END);
  125.         enroll($1, gencode());
  126.     }
  127. |   action {
  128.         enroll(genrule(NULL, NULL), $1);
  129.     }
  130. |
  131. ;
  132. declaration:
  133.     T_USER '(' optional_parameter_list ')' {
  134.         yydisplay = $3;
  135.         $$ = ((IDENT*)($1))->vfunc = newfunction();
  136.     }
  137. ;
  138. optional_parameter_list:
  139.     parameter_list {
  140.         $$ = $1;
  141.     }
  142. |   {
  143.         $$ = 0;
  144.     }
  145. ;
  146. parameter_list:
  147.     parameter_list comma T_NAME {
  148.         $$ = newelement($1, $3);
  149.     }
  150. |   T_NAME {
  151.         $$ = newelement(NULL, $1);
  152.     }
  153. ;
  154. body:
  155.     '{' {
  156.         pushstack(L_MARK);
  157.     } statement_list '}' {
  158.         popstack(L_MARK);
  159.         if (stacktop != stackbot + MAXSTACK)
  160.             yyerror("body jump stack");
  161.         if (lastcode() != C_RETURN) {
  162.             genaddr(lookfor(nul));
  163.             genbyte(C_LOAD);
  164.             genbyte(C_RETURN);
  165.         }
  166.         genbyte(C_END);
  167.         $$ = gencode();
  168.     }
  169. ;
  170. pattern:
  171.     pattern_predicate comma pattern_predicate {
  172.         $$ = genrule($1, $3);
  173.     }
  174. |   pattern_predicate {
  175.         $$ = genrule($1, NULL);
  176.     }
  177. ;
  178. pattern_predicate:
  179.     pattern_disjunction {
  180.         genbyte(C_END);
  181.         $$ = gencode();
  182.     }
  183. ;
  184. pattern_disjunction:
  185.     pattern_conjunction
  186. |   pattern_disjunction T_LIOR eol {
  187.         yyl1 = getlabel();
  188.         pushlabel(L_NORMAL, yyl1);
  189.         genjump(C_OJMP, yyl1);
  190.     } pattern_conjunction {
  191.         yyl1 = poplabel();
  192.         genlabel(yyl1);
  193.         putlabel(yyl1);
  194.         $$ = S_LONG;
  195.     }
  196. ;
  197. pattern_conjunction:
  198.     pattern_expression
  199. |   pattern_conjunction T_LAND eol {
  200.         yyl1 = getlabel();
  201.         pushlabel(L_NORMAL, yyl1);
  202.         genjump(C_AJMP, yyl1);
  203.     } pattern_expression {
  204.         yyl1 = poplabel();
  205.         genlabel(yyl1);
  206.         putlabel(yyl1);
  207.         $$ = S_LONG;
  208.     }
  209. ;
  210. pattern_expression:
  211.     field_zero_match
  212. |   '!' field_zero_match {
  213.         genbyte(C_NOT);
  214.         $$ = S_SHORT;
  215.     }
  216. |   '(' pattern_disjunction ')' {
  217.         $$ = $2;
  218.     }
  219. |   '!' '(' pattern_disjunction ')' {
  220.         genbyte(C_NOT);
  221.         $$ = S_SHORT;
  222.     }
  223. |   membership
  224. ;
  225. field_zero_match:
  226.     regular_expression {
  227.         genfield(0);
  228.         lastop(C_PLUCK);
  229.         genbyte(C_SWAP);
  230.         genbyte(C_MAT);
  231.         $$ = S_SHORT;
  232.     }
  233. ;
  234. action:
  235.     '{' {
  236.         pushstack(L_MARK);
  237.     } statement_list '}' {
  238.         popstack(L_MARK);
  239.         if (stacktop != stackbot + MAXSTACK)
  240.             yyerror("action jump stack");
  241.         genbyte(C_END);
  242.         $$ = gencode();
  243.     }
  244. ;
  245. statement_list:
  246.     statement_list eos else_part
  247. |   statement
  248. ;
  249. else_part:
  250.     T_ELSE eol {
  251.         yyl1 = toploop(L_ELSE);
  252.         if (yyl1 < 0)
  253.             yyerror("syntax error");
  254.         yyl1 = getloop(L_ELSE);
  255.         pushlabel(L_ELSE, yyl1);
  256.         yyl2 = getlabel();
  257.         genjump(C_JUMP, yyl2);
  258.         genlabel(yyl1);
  259.         uselabel(yyl1, yyl2);
  260.         putlabel(yyl2);
  261.     } statement
  262. |   {
  263.         while (stackptr->sclass >= L_FOR)
  264.             popstack(stackptr->sclass);
  265.     } statement
  266. ;
  267. statement:
  268.     expression {
  269.         gendrop();
  270.     }
  271. |   '{' {
  272.         pushstack(L_MARK);
  273.     } statement_list {
  274.         popstack(L_MARK);
  275.     } '}'
  276. |   T_IF '(' expression ')' eol {
  277.         yyl1 = getlabel();
  278.         pushlabel(L_ELSE, yyl1);
  279.         genjump(C_FJMP, yyl1);
  280.     } statement
  281. |   T_WHILE {
  282.         yyl1 = getlabel();
  283.         yyl2 = getlabel();
  284.         pushlabel(L_BREAK, yyl1);
  285.         pushlabel(L_CONTINUE, yyl2);
  286.         pushstack(L_WHILE);
  287.         genlabel(yyl2);
  288.     } '(' expression ')' eol {
  289.         yyl1 = toploop(L_BREAK);
  290.         genjump(C_FJMP, yyl1);
  291.     } statement
  292. |   T_DO eol {
  293.         yyl1 = getlabel();
  294.         yyl2 = getlabel();
  295.         yyl3 = getlabel();
  296.         pushlabel(L_NORMAL, yyl1);
  297.         pushlabel(L_BREAK, yyl2);
  298.         pushlabel(L_CONTINUE, yyl3);
  299.         pushstack(L_DONE);
  300.         genlabel(yyl1);
  301.         yydone = 1;
  302.     } statement
  303. |   T_DONE {
  304.         popstack(L_DONE);
  305.         yyl1 = toploop(L_CONTINUE);
  306.         genlabel(yyl1);
  307.         yydone = 0;
  308.     } '(' expression ')' {
  309.         yyl1 = poplabel();
  310.         yyl2 = poplabel();
  311.         yyl3 = poplabel();
  312.         genjump(C_TJMP, yyl3);
  313.         genlabel(yyl2);
  314.         putlabel(yyl1);
  315.         putlabel(yyl2);
  316.         putlabel(yyl3);
  317.     }
  318. |   T_FOR '(' variable T_IN variable_name ')' eol {
  319.         yyl1 = getlabel();
  320.         yyl2 = getlabel();
  321.         pushlabel(L_BREAK, yyl1);
  322.         pushlabel(L_CONTINUE, yyl2);
  323.         pushstack(L_FOR);
  324.         genbyte(C_LOAD);
  325.         genlabel(yyl2);
  326.         genjump(C_IJMP, yyl1);
  327.     } statement
  328. |   T_FOR '(' optional_statement ';' {
  329.         yyl1 = getlabel();
  330.         yyl2 = getlabel();
  331.         pushlabel(L_BREAK, yyl1);
  332.         pushlabel(L_CONTINUE, yyl2);
  333.         pushstack(L_FOR);
  334.         yyl1 = getlabel();
  335.         yyl2 = getlabel();
  336.         pushlabel(L_NORMAL, yyl1);
  337.         pushlabel(L_NORMAL, yyl2);
  338.         genlabel(yyl1);
  339.     } for_test
  340. |   T_BREAK {
  341.         yyl1 = toploop(L_BREAK);
  342.         if (yyl1 < 0) {
  343.             yyerror("invalid break");
  344.             YYERROR;
  345.         }
  346.         genjump(C_JUMP, yyl1);
  347.     }
  348. |   T_CONTINUE {
  349.         yyl1 = toploop(L_CONTINUE);
  350.         if (yyl1 < 0) {
  351.             yyerror("invalid continue");
  352.             YYERROR;
  353.         }
  354.         genjump(C_JUMP, yyl1);
  355.     }
  356. |   T_RETURN return_expression {
  357.         genbyte(C_RETURN);
  358.     }
  359. |   T_SRAND '(' optional_expression ')' {
  360.         gencall(P_SRAND, $3);
  361.     }
  362. |   T_PRINT '(' expression_list ')' output_file {
  363.         gencall(P_PRINT, $3+1);
  364.     }
  365. |   T_PRINT optional_print_list output_file {
  366.         gencall(P_PRINT, $2+1);
  367.     }
  368. |   T_PRINTF '(' expression_list ')' output_file {
  369.         gencall(P_PRINTF, $3+1);
  370.     }
  371. |   T_PRINTF print_expression_list output_file {
  372.         gencall(P_PRINTF, $2+1);
  373.     }
  374. |   T_CLOSE '('  expression ')' {
  375.         gencall(P_CLOSE, 1);
  376.     }
  377. |   T_DELETE variable_name '[' expression_list ']' {
  378.         if ($4 > 1)
  379.             gencall(P_JOIN, $4);
  380.         gencall(P_DELETE, 2);
  381.     }
  382. |   T_NEXT {
  383.         gencall(P_NEXT, 0);
  384.     }
  385. |   T_EXIT optional_expression {
  386.         gencall(P_EXIT, $2);
  387.     }
  388. |
  389. ;
  390. optional_expression:
  391.     expression {
  392.         $$ = 1;
  393.     }
  394. |   {
  395.         $$ = 0;
  396.     }
  397. ;
  398. for_test:
  399.     ';' {
  400.         yyl1 = toploop(L_NORMAL);
  401.         yyl2 = toploop(L_CONTINUE);
  402.         genjump(C_JUMP, yyl1);
  403.         genlabel(yyl2);
  404.     } optional_statement ')' eol {
  405.         yyl1 = poplabel();
  406.         yyl2 = poplabel();
  407.         genlabel(yyl1);
  408.         putlabel(yyl1);
  409.         putlabel(yyl2);
  410.     } statement
  411. |   expression ';' {
  412.         yyl1 = toploop(L_BREAK);
  413.         genjump(C_FJMP, yyl1);
  414.     } for_next
  415. ;
  416. for_next:
  417.     ')' eol {
  418.         yyl1 = poplabel();
  419.         yyl2 = poplabel();
  420.         yyl3 = toploop(L_CONTINUE);
  421.         uselabel(yyl3, yyl2);
  422.         putlabel(yyl1);
  423.         putlabel(yyl2);
  424.     } statement
  425. |   {
  426.         yyl1 = toploop(L_NORMAL);
  427.         yyl2 = toploop(L_CONTINUE);
  428.         genjump(C_JUMP, yyl1);
  429.         genlabel(yyl2);
  430.     } expression ')' eol {
  431.         yyl1 = poplabel();
  432.         yyl2 = poplabel();
  433.         gendrop();
  434.         genjump(C_JUMP, yyl2);
  435.         genlabel(yyl1);
  436.         putlabel(yyl1);
  437.         putlabel(yyl2);
  438.     } statement
  439. ;
  440. optional_statement:
  441.     expression {
  442.         gendrop();
  443.     }
  444. |
  445. ;
  446. optional_print_list:
  447.     print_expression_list {
  448.         $$ = $1;
  449.     }
  450. |   {
  451.         genfield(0);
  452.         lastop(C_PLUCK);
  453.         $$ = 1;
  454.     }
  455. ;
  456. return_expression:
  457.     expression
  458. |   {
  459.         genaddr(lookfor(nul));
  460.         genbyte(C_LOAD);
  461.     }
  462. ;
  463. output_file:
  464.     '>' factor {
  465.         gencall(P_CREATE, 1);
  466.     }
  467. |   T_APPEND factor {
  468.         gencall(P_APPEND, 1);
  469.     }
  470. |   {
  471.         genfcon(0);
  472.     }
  473. ;
  474. input_file:
  475.     '<' factor {
  476.         gencall(P_OPEN, 1);
  477.     }
  478. |   {
  479.         genfcon(1);
  480.     }
  481. ;
  482. regular_expression:
  483.     '/' {
  484.         genrcon(regexp(1));
  485.         $$ = S_REGEXP;
  486.     }
  487. ;
  488. print_expression:
  489.     variable T_STORE print_expression {
  490.         genstore($2);
  491.         $$ = $3;
  492.     }
  493. |   print_conditional
  494. ;
  495. print_conditional:
  496.     print_disjunction {
  497.         if ($1 == S_LONG)
  498.             genbyte(C_IS);
  499.         $$ = S_SHORT;
  500.     }
  501. |   print_disjunction '?' {
  502.         yyl1 = getlabel();
  503.         yyl2 = getlabel();
  504.         pushlabel(L_NORMAL, yyl1);
  505.         pushlabel(L_NORMAL, yyl2);
  506.         genjump(C_FJMP, yyl2);
  507.     } print_expression ':' {
  508.         yyl1 = poplabel();
  509.         yyl2 = toploop(L_NORMAL);
  510.         genjump(C_JUMP, yyl2);
  511.         genlabel(yyl1);
  512.         putlabel(yyl1);
  513.     } print_expression {
  514.         yyl1 = poplabel();
  515.         genlabel(yyl1);
  516.         putlabel(yyl1);
  517.         $$ = S_NUMBER;
  518.     }
  519. ;
  520. print_disjunction:
  521.     print_conjunction
  522. |   print_disjunction T_LIOR eol {
  523.         yyl1 = getlabel();
  524.         pushlabel(L_NORMAL, yyl1);
  525.         genjump(C_OJMP, yyl1);
  526.     } print_conjunction {
  527.         yyl1 = poplabel();
  528.         genlabel(yyl1);
  529.         putlabel(yyl1);
  530.         $$ = S_LONG;
  531.     }
  532. ;
  533. print_conjunction:
  534.     print_membership
  535. |   print_conjunction T_LAND eol {
  536.         yyl1 = getlabel();
  537.         pushlabel(L_NORMAL, yyl1);
  538.         genjump(C_AJMP, yyl1);
  539.     } print_membership {
  540.         yyl1 = poplabel();
  541.         genlabel(yyl1);
  542.         putlabel(yyl1);
  543.         $$ = S_LONG;
  544.     }
  545. ;
  546. print_membership:
  547.    '(' expression_list ')' T_IN {
  548.         if ($2 > 1)
  549.             gencall(P_JOIN, $2);
  550.     } variable_name {
  551.         genbyte(C_IN);
  552.         $$ = S_SHORT;
  553.     }
  554. |   print_match T_IN variable_name {
  555.         genbyte(C_IN);
  556.         $$ = S_SHORT;
  557.     }
  558. |   print_match
  559. ;
  560. print_match:
  561.     concatenation
  562. |   concatenation '~' match_concatenation {
  563.         genbyte(C_MAT);
  564.         $$ = S_SHORT;
  565.     }
  566. |   concatenation T_NOMATCH match_concatenation {
  567.         genbyte(C_MAT);
  568.         genbyte(C_NOT);
  569.         $$ = S_SHORT;
  570.     }
  571. ;
  572. match_concatenation:
  573.     regular_expression
  574. |   concatenation
  575. ;
  576. print_expression_list:
  577.     print_expression_list comma print_expression {
  578.         $$ = $1 + 1;
  579.     }
  580. |   print_expression {
  581.         $$ = 1;
  582.     }
  583. ;
  584. expression:
  585.     variable T_STORE expression {
  586.         genstore($2);
  587.         $$ = $3;
  588.     }
  589. |   conditional
  590. ;
  591. conditional:
  592.     disjunction {
  593.         if ($1 == S_LONG)
  594.             genbyte(C_IS);
  595.         $$ = S_SHORT;
  596.     }
  597. |   disjunction '?' {
  598.         yyl1 = getlabel();
  599.         yyl2 = getlabel();
  600.         pushlabel(L_NORMAL, yyl1);
  601.         pushlabel(L_NORMAL, yyl2);
  602.         genjump(C_FJMP, yyl2);
  603.     } expression ':' {
  604.         yyl1 = poplabel();
  605.         yyl2 = toploop(L_NORMAL);
  606.         genjump(C_JUMP, yyl2);
  607.         genlabel(yyl1);
  608.         putlabel(yyl1);
  609.     } expression {
  610.         yyl1 = poplabel();
  611.         genlabel(yyl1);
  612.         putlabel(yyl1);
  613.         $$ = S_NUMBER;
  614.     }
  615. ;
  616. disjunction:
  617.     conjunction
  618. |   disjunction T_LIOR eol {
  619.         yyl1 = getlabel();
  620.         pushlabel(L_NORMAL, yyl1);
  621.         genjump(C_OJMP, yyl1);
  622.     } conjunction {
  623.         yyl1 = poplabel();
  624.         genlabel(yyl1);
  625.         putlabel(yyl1);
  626.         $$ = S_LONG;
  627.     }
  628. ;
  629. conjunction:
  630.     membership
  631. |   conjunction T_LAND eol {
  632.         yyl1 = getlabel();
  633.         pushlabel(L_NORMAL, yyl1);
  634.         genjump(C_AJMP, yyl1);
  635.     } membership {
  636.         yyl1 = poplabel();
  637.         genlabel(yyl1);
  638.         putlabel(yyl1);
  639.         $$ = S_LONG;
  640.     }
  641. ;
  642. membership:
  643.    '(' expression_list ')' T_IN {
  644.         if ($2 > 1)
  645.             gencall(P_JOIN, $2);
  646.     } variable_name {
  647.         genbyte(C_IN);
  648.         $$ = S_SHORT;
  649.     }
  650. |   match T_IN variable_name {
  651.         genbyte(C_IN);
  652.         $$ = S_SHORT;
  653.     }
  654. |   match
  655. ;
  656. match:
  657.     relation
  658. |   relation '~' match_relation {
  659.         genbyte(C_MAT);
  660.         $$ = S_SHORT;
  661.     }
  662. |   relation T_NOMATCH match_relation {
  663.         genbyte(C_MAT);
  664.         genbyte(C_NOT);
  665.         $$ = S_SHORT;
  666.     }
  667. ;
  668. relation:
  669.     concatenation
  670. |   concatenation T_RELOP concatenation {
  671.         genbyte($2);
  672.         $$ = S_SHORT;
  673.     }
  674. |   concatenation '<' concatenation {
  675.         genbyte(C_LT);
  676.         $$ = S_SHORT;
  677.     }
  678. |   concatenation '>' concatenation {
  679.         genbyte(C_GT);
  680.         $$ = S_SHORT;
  681.     }
  682. ;
  683. concatenation:
  684.     arithmetic
  685. |   concatenation arithmetic {
  686.         genbyte(C_CAT);
  687.         $$ = S_STRING;
  688.     }
  689. ;
  690. arithmetic:
  691.     term
  692. |   arithmetic '+' term {
  693.         genbyte(C_ADD);
  694.         $$ = S_DOUBLE;
  695.     }
  696. |   arithmetic '-' term {
  697.         genbyte(C_SUB);
  698.         $$ = S_DOUBLE;
  699.     }
  700. ;
  701. term:
  702.     unary
  703. |   term '*' unary {
  704.         genbyte(C_MUL);
  705.         $$ = S_DOUBLE;
  706.     }
  707. |   term '/' unary {
  708.         genbyte(C_DIV);
  709.         $$ = S_DOUBLE;
  710.     }
  711. |   term '%' unary {
  712.         genbyte(C_MOD);
  713.         $$ = S_DOUBLE;
  714.     }
  715. ;
  716. unary:
  717.     exponential
  718. |   '!' exponential {
  719.         genbyte(C_NOT);
  720.         $$ = S_DOUBLE;
  721.     }
  722. |   '-' exponential %prec T_SIGN {
  723.         genbyte(C_NEG);
  724.         $$ = S_DOUBLE;
  725.     }
  726. |   '+' exponential %prec T_SIGN {
  727.         genbyte(C_NUM);
  728.         $$ = S_DOUBLE;
  729.     }
  730. ;
  731. exponential:
  732.     factor
  733. |   factor '^' exponential {
  734.         genbyte(C_POW);
  735.         $$ = S_DOUBLE;
  736.     }
  737. ;
  738. factor:
  739.     T_INCOP variable {
  740.         gentwo(C__PRE, $1);
  741.         $$ = S_DOUBLE;
  742.     }
  743. |   variable T_INCOP {
  744.         gentwo(C__POST, $2);
  745.         $$ = S_DOUBLE;
  746.     }
  747. |   variable {
  748.         if (lastcode() == C_ADDR)
  749.             lastop(C_FETCH);
  750.         else if (lastcode() == C_FIELD)
  751.             lastop(C_PLUCK);
  752.         else
  753.             genbyte(C_LOAD);
  754.         $$ = S_NUMBER;
  755.     }
  756. |   '(' expression ')' %prec T_GROUP {
  757.         $$ = S_NUMBER;
  758.     }
  759. |   T_DCON {
  760.         gendcon($1);
  761.         $$ = S_DOUBLE;
  762.     }
  763. |   T_SCON {
  764.         genscon($1);
  765.         $$ = S_STRING;
  766.     }
  767. |   T_USER '(' optional_argument_list ')' {
  768.         genuser($1, $3);
  769.         $$ = S_NUMBER;
  770.     }
  771. |   T_FUNC0 '(' ')' {
  772.         genbyte($1);
  773.         $$ = S_NUMBER;
  774.     }
  775. |   T_FUNC1 '(' expression ')' {
  776.         genbyte($1);
  777.         $$ = S_NUMBER;
  778.     }
  779. |   T_FUNC2 '(' expression comma expression ')' {
  780.         genbyte($1);
  781.         $$ = S_NUMBER;
  782.     }
  783. |   T_SUB '(' match_expression comma expression ')' {
  784.         genfield(0);
  785.         genfield(0);
  786.         lastop(C_PLUCK);
  787.         gencall($1, 4);
  788.         $$ = S_STRING;
  789.     }
  790. |   T_SUB '(' match_expression comma expression comma variable ')' {
  791.         genbyte(C_DUP);
  792.         genbyte(C_LOAD);
  793.         gencall($1, 4);
  794.         $$ = S_STRING;
  795.     }
  796. |   T_SUB '(' match_expression comma expression comma expression ')' {
  797.         genaddr(lookfor(nul));
  798.         genbyte(C_SWAP);
  799.         gencall($1, 4);
  800.         $$ = S_STRING;
  801.     }
  802. |   T_SPLIT '(' expression comma variable_name ')' {
  803.         genaddr(lookfor(fs));
  804.         genbyte(C_LOAD);
  805.         gencall(P_SPLIT, 3);
  806.         $$ = S_DOUBLE;
  807.     }
  808. |   T_SPLIT '(' expression comma variable_name comma expression ')' {
  809.         gencall(P_SPLIT, 3);
  810.         $$ = S_DOUBLE;
  811.     }
  812. |   T_MATCH '(' expression comma match_expression ')' {
  813.         gencall(P_MATCH, 2);
  814.         $$ = S_SHORT;
  815.     }
  816. |   T_INDEX '(' expression ')' {
  817.         genfield(0);
  818.         lastop(C_PLUCK);
  819.         genbyte(C_SWAP);
  820.         gencall(P_INDEX, 2);
  821.         $$ = S_DOUBLE;
  822.     }
  823. |   T_INDEX '(' expression comma expression ')' {
  824.         gencall(P_INDEX, 2);
  825.         $$ = S_DOUBLE;
  826.     }
  827. |   T_SUBSTR '(' expression comma expression ')' {
  828.         gencall(P_SUBSTR, 2);
  829.         $$ = S_STRING;
  830.     }
  831. |   T_SUBSTR '(' expression comma expression comma expression ')' {
  832.         gencall(P_SUBSTR, 3);
  833.         $$ = S_STRING;
  834.     }
  835. |   T_SPRINTF '(' expression_list ')' {
  836.         gencall(P_SPRINTF, $3);
  837.         $$ = S_DOUBLE;
  838.     }
  839. |   T_GETLINE variable input_file {
  840.         gencall(P_GETLINE, 2);
  841.         $$ = S_DOUBLE;
  842.     }
  843. |   T_GETLINE input_file {
  844.         genfield(0);
  845.         genbyte(C_SWAP);
  846.         gencall(P_GETLINE, 2);
  847.         $$ = S_DOUBLE;
  848.     }
  849. ;
  850. match_relation:
  851.     regular_expression
  852. |   relation
  853. ;
  854. match_expression:
  855.     regular_expression
  856. |   expression
  857. ;
  858. expression_list:
  859.     expression_list comma expression {
  860.         $$ = $1 + 1;
  861.     }
  862. |   expression {
  863.         $$ = 1;
  864.     }
  865. ;
  866. optional_argument_list:
  867.     expression_list {
  868.         $$ = $1;
  869.     }
  870. |   {
  871.         $$ = 0;
  872.     }
  873. ;
  874. variable:
  875.     '$' factor {
  876.         if (lastcode() == C_DCON)
  877.             genfield(lastdcon());
  878.         else
  879.             genbyte(C_DOLAR);
  880.     }
  881. |   variable_name '[' expression_list ']' {
  882.         if ($3 > 1)
  883.             gencall(P_JOIN, $3);
  884.         genbyte(C_SELECT);
  885.     }
  886. |   variable_name
  887. ;
  888. variable_name:
  889.     T_NAME {
  890.         genaddr($1);
  891.     }
  892. ;
  893. comma:
  894.     ',' eol
  895. ;
  896. eos:
  897.     ';'
  898. |   T_EOL
  899. ;
  900. eol:
  901.     T_EOL
  902. |
  903. ;
  904. %%
  905. int     yydone;
  906. int     yyl1, yyl2, yyl3;
  907. LIST    *yydisplay;
  908.  
  909. static int toploop(int);
  910. static int getloop(int);
  911. static int poplabel(void);
  912.  
  913. static void popstack(int);
  914. static void pushstack(int);
  915. static void pushlabel(int, int);
  916.  
  917. static void enroll(void*, void*);
  918.  
  919. static void *newfunction(void);
  920. static void *newelement(void*, void*);
  921.  
  922. IDENT *lookfor(ITEM *sp)
  923. {
  924.     IDENT *vp;
  925.  
  926.     for (vp = ident; vp != NULL; vp = vp->vnext)
  927.         if (vp->vitem == sp)
  928.             return vp;
  929.     return NULL;
  930. }
  931.  
  932. static void enroll(rule, action)
  933. void *rule;
  934. void *action;
  935. {
  936.     if (rulep == NULL) {
  937.         rulep = rule;
  938.         rules = rulep;
  939.     }
  940.     else {
  941.         rulep->next = rule;
  942.         rulep = rule;
  943.     }
  944.     rulep->next = NULL;
  945.     rulep->action = action;
  946. }
  947.  
  948. static void*
  949. newelement(next, item)
  950. void *next;
  951. void *item;
  952. {
  953.     LIST    *lp;
  954.  
  955.     lp = yyalloc(sizeof(LIST));
  956.     lp->litem = item;
  957.     lp->lnext = next;
  958.     return lp;
  959. }
  960.  
  961. static void*
  962. newfunction()
  963. {
  964.     int     size;
  965.     FUNC    *fp;
  966.     LIST    *lp;
  967.  
  968.     size = 0;
  969.     lp = yydisplay;
  970.     while (lp != NULL) {
  971.         size++;
  972.         lp = lp->lnext;
  973.     }
  974.     fp = yyalloc(sizeof(FUNC));
  975.     fp->psize = size;
  976.     fp->plist = yydisplay;
  977.     fp->pcode = NULL;
  978.     return fp;
  979. }
  980.  
  981. static void
  982. pushstack(kind)
  983. {
  984.     if (stackptr <= stackbot)
  985.         yyerror("Stack overflow");
  986.     stackptr--;
  987.     stackptr->sclass = kind;
  988.     stackptr->svalue.ival = 0;
  989.     if (kind == L_MARK || kind == L_DONE) {
  990.         stackptr->stype = yydone;
  991.         stackptr->svalue.sptr = stacktop;
  992.         stacktop = stackptr;
  993.         yydone = 0;
  994.     }
  995. }
  996.  
  997. static void popstack(kind)
  998. {
  999.     int     i, j, class;
  1000.  
  1001.     while (stackptr < stacktop) {
  1002.         class = stackptr->sclass;
  1003.         if ( class == L_FOR || class == L_WHILE) {
  1004.             stackptr++;
  1005.             i = poplabel();
  1006.             j = poplabel();
  1007.             genjump(C_JUMP, i);
  1008.             genlabel(j);
  1009.             putlabel(i);
  1010.             putlabel(j);
  1011.         }
  1012.         else if (class == L_ELSE) {
  1013.             i = poplabel();
  1014.             genlabel(i);
  1015.             putlabel(i);
  1016.         }
  1017.         else
  1018.             yyerror("dangling label");
  1019.         if (class == kind)
  1020.             return;
  1021.     }
  1022.     if (kind == L_MARK || kind == L_DONE) {
  1023.         yydone = stackptr->stype;
  1024.         stacktop = stackptr->svalue.sptr;
  1025.         stackptr++;
  1026.     }
  1027.     else
  1028.         yyerror("syntax error");
  1029. }
  1030.  
  1031. static int toploop(int class)
  1032. {
  1033.     ITEM    *sp;
  1034.     int     label;
  1035.  
  1036.     sp = stackptr;
  1037.     while (sp < stackbot + MAXSTACK)
  1038.         if (sp->sclass == class) {
  1039.             label = sp->svalue.ival;
  1040. #ifdef LDEBUG
  1041.     printlabel("top", label);
  1042. #endif
  1043.             return label;
  1044.         }
  1045.         else
  1046.             sp++;
  1047.     return(-1);
  1048. }
  1049.  
  1050. static int getloop(class)
  1051. {
  1052.     while (stackptr < stacktop) {
  1053.         if (stackptr->sclass == class)
  1054.             return poplabel();
  1055.         else
  1056.             popstack(stackptr->sclass);
  1057.     }
  1058.     return(-1);
  1059. }
  1060.  
  1061. static void
  1062. pushlabel(class, label)
  1063. {
  1064. #ifdef LDEBUG
  1065.     printlabel("pop", label);
  1066. #endif
  1067.     if (stackptr <= stackbot)
  1068.         yyerror("Stack overflow");
  1069.     stackptr--;
  1070.     stackptr->sclass = class;
  1071.     stackptr->svalue.ival = label;
  1072. }
  1073.  
  1074. static int
  1075. poplabel()
  1076. {
  1077.     int     label;
  1078.  
  1079.     label = stackptr->svalue.ival;
  1080. #ifdef LDEBUG
  1081.     printlabel("pop", label);
  1082. #endif
  1083.     stackptr++;
  1084.     return label;
  1085. }
  1086.  
  1087.