syn.y 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. %term FOR IN WHILE IF NOT TWIDDLE BANG SUBSHELL SWITCH FN
  2. %term WORD REDIR DUP PIPE SUB
  3. %term SIMPLE ARGLIST WORDS BRACE PAREN PCMD PIPEFD /* not used in syntax */
  4. /* operator priorities -- lowest first */
  5. %left IF WHILE FOR SWITCH ')' NOT
  6. %left ANDAND OROR
  7. %left BANG SUBSHELL
  8. %left PIPE
  9. %left '^'
  10. %right '$' COUNT '"'
  11. %left SUB
  12. %{
  13. #include "rc.h"
  14. #include "fns.h"
  15. %}
  16. %union{
  17. struct tree *tree;
  18. };
  19. %type<tree> line paren brace body cmdsa cmdsan assign epilog redir
  20. %type<tree> cmd simple first word comword keyword words
  21. %type<tree> NOT FOR IN WHILE IF TWIDDLE BANG SUBSHELL SWITCH FN
  22. %type<tree> WORD REDIR DUP PIPE
  23. %%
  24. rc: { return 1;}
  25. | line '\n' {return !compile($1);}
  26. line: cmd
  27. | cmdsa line {$$=tree2(';', $1, $2);}
  28. body: cmd
  29. | cmdsan body {$$=tree2(';', $1, $2);}
  30. cmdsa: cmd ';'
  31. | cmd '&' {$$=tree1('&', $1);}
  32. cmdsan: cmdsa
  33. | cmd '\n'
  34. brace: '{' body '}' {$$=tree1(BRACE, $2);}
  35. paren: '(' body ')' {$$=tree1(PCMD, $2);}
  36. assign: first '=' word {$$=tree2('=', $1, $3);}
  37. epilog: {$$=0;}
  38. | redir epilog {$$=mung2($1, $1->child[0], $2);}
  39. redir: REDIR word {$$=mung1($1, $1->rtype==HERE?heredoc($2):$2);}
  40. | DUP
  41. cmd: {$$=0;}
  42. | brace epilog {$$=epimung($1, $2);}
  43. | IF paren {skipnl();} cmd
  44. {$$=mung2($1, $2, $4);}
  45. | IF NOT {skipnl();} cmd {$$=mung1($2, $4);}
  46. | FOR '(' word IN words ')' {skipnl();} cmd
  47. /*
  48. * if ``words'' is nil, we need a tree element to distinguish between
  49. * for(i in ) and for(i), the former being a loop over the empty set
  50. * and the latter being the implicit argument loop. so if $5 is nil
  51. * (the empty set), we represent it as "()". don't parenthesize non-nil
  52. * functions, to avoid growing parentheses every time we reread the
  53. * definition.
  54. */
  55. {$$=mung3($1, $3, $5 ? $5 : tree1(PAREN, $5), $8);}
  56. | FOR '(' word ')' {skipnl();} cmd
  57. {$$=mung3($1, $3, (struct tree *)0, $6);}
  58. | WHILE paren {skipnl();} cmd
  59. {$$=mung2($1, $2, $4);}
  60. | SWITCH word {skipnl();} brace
  61. {$$=tree2(SWITCH, $2, $4);}
  62. | simple {$$=simplemung($1);}
  63. | TWIDDLE word words {$$=mung2($1, $2, $3);}
  64. | cmd ANDAND cmd {$$=tree2(ANDAND, $1, $3);}
  65. | cmd OROR cmd {$$=tree2(OROR, $1, $3);}
  66. | cmd PIPE cmd {$$=mung2($2, $1, $3);}
  67. | redir cmd %prec BANG {$$=mung2($1, $1->child[0], $2);}
  68. | assign cmd %prec BANG {$$=mung3($1, $1->child[0], $1->child[1], $2);}
  69. | BANG cmd {$$=mung1($1, $2);}
  70. | SUBSHELL cmd {$$=mung1($1, $2);}
  71. | FN words brace {$$=tree2(FN, $2, $3);}
  72. | FN words {$$=tree1(FN, $2);}
  73. simple: first
  74. | simple word {$$=tree2(ARGLIST, $1, $2);}
  75. | simple redir {$$=tree2(ARGLIST, $1, $2);}
  76. first: comword
  77. | first '^' word {$$=tree2('^', $1, $3);}
  78. word: keyword {lastword=1; $1->type=WORD;}
  79. | comword
  80. | word '^' word {$$=tree2('^', $1, $3);}
  81. comword: '$' word {$$=tree1('$', $2);}
  82. | '$' word SUB words ')' {$$=tree2(SUB, $2, $4);}
  83. | '"' word {$$=tree1('"', $2);}
  84. | COUNT word {$$=tree1(COUNT, $2);}
  85. | WORD
  86. | '`' brace {$$=tree1('`', $2);}
  87. | '(' words ')' {$$=tree1(PAREN, $2);}
  88. | REDIR brace {$$=mung1($1, $2); $$->type=PIPEFD;}
  89. keyword: FOR|IN|WHILE|IF|NOT|TWIDDLE|BANG|SUBSHELL|SWITCH|FN
  90. words: {$$=(struct tree*)0;}
  91. | words word {$$=tree2(WORDS, $1, $2);}