PageRenderTime 64ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/usr.bin/awk/awkgram.y

https://bitbucket.org/warthurton/gno
Happy | 487 lines | 428 code | 59 blank | 0 comment | 0 complexity | 1720866c0d55c06d5b3e91499458c084 MD5 | raw file
Possible License(s): AGPL-1.0
  1. /****************************************************************
  2. Copyright (C) Lucent Technologies 1997
  3. All Rights Reserved
  4. Permission to use, copy, modify, and distribute this software and
  5. its documentation for any purpose and without fee is hereby
  6. granted, provided that the above copyright notice appear in all
  7. copies and that both that the copyright notice and this
  8. permission notice and warranty disclaimer appear in supporting
  9. documentation, and that the name Lucent Technologies or any of
  10. its entities not be used in advertising or publicity pertaining
  11. to distribution of the software without specific, written prior
  12. permission.
  13. LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  14. INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
  15. IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
  16. SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  17. WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  18. IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  19. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
  20. THIS SOFTWARE.
  21. ****************************************************************/
  22. /* $Id: awkgram.y 563 1998-04-07 16:19:01Z tribby $ */
  23. %{
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include "awk.h"
  27. void checkdup(Node *list, Cell *item);
  28. int yywrap(void) { return(1); }
  29. Node *beginloc = 0;
  30. Node *endloc = 0;
  31. int infunc = 0; /* = 1 if in arglist or body of func */
  32. int inloop = 0; /* = 1 if in while, for, do */
  33. char *curfname = 0; /* current function name */
  34. Node *arglist = 0; /* list of args for current function */
  35. %}
  36. %union {
  37. Node *p;
  38. Cell *cp;
  39. int i;
  40. char *s;
  41. }
  42. %token <i> FIRSTTOKEN /* must be first */
  43. %token <p> PROGRAM PASTAT PASTAT2 XBEGIN XEND
  44. %token <i> NL ',' '{' '(' '|' ';' '/' ')' '}' '[' ']'
  45. %token <i> ARRAY
  46. %token <i> MATCH NOTMATCH MATCHOP
  47. %token <i> FINAL DOT ALL CCL NCCL CHAR OR STAR QUEST PLUS
  48. %token <i> AND BOR APPEND EQ GE GT LE LT NE IN
  49. %token <i> ARG BLTIN BREAK CLOSE CONTINUE DELETE DO EXIT FOR FUNC
  50. %token <i> SUB GSUB IF INDEX LSUBSTR MATCHFCN NEXT NEXTFILE
  51. %token <i> ADD MINUS MULT DIVIDE MOD
  52. %token <i> ASSIGN ASGNOP ADDEQ SUBEQ MULTEQ DIVEQ MODEQ POWEQ
  53. %token <i> PRINT PRINTF SPRINTF
  54. %token <p> ELSE INTEST CONDEXPR
  55. %token <i> POSTINCR PREINCR POSTDECR PREDECR
  56. %token <cp> VAR IVAR VARNF CALL NUMBER STRING
  57. %token <s> REGEXPR
  58. %type <p> pas pattern ppattern plist pplist patlist prarg term re
  59. %type <p> pa_pat pa_stat pa_stats
  60. %type <s> reg_expr
  61. %type <p> simple_stmt opt_simple_stmt stmt stmtlist
  62. %type <p> var varname funcname varlist
  63. %type <p> for if else while
  64. %type <i> do st
  65. %type <i> pst opt_pst lbrace rbrace rparen comma nl opt_nl and bor
  66. %type <i> subop print
  67. %right ASGNOP
  68. %right '?'
  69. %right ':'
  70. %left BOR
  71. %left AND
  72. %left GETLINE
  73. %nonassoc APPEND EQ GE GT LE LT NE MATCHOP IN '|'
  74. %left ARG BLTIN BREAK CALL CLOSE CONTINUE DELETE DO EXIT FOR FUNC
  75. %left GSUB IF INDEX LSUBSTR MATCHFCN NEXT NUMBER
  76. %left PRINT PRINTF RETURN SPLIT SPRINTF STRING SUB SUBSTR
  77. %left REGEXPR VAR VARNF IVAR WHILE '('
  78. %left CAT
  79. %left '+' '-'
  80. %left '*' '/' '%'
  81. %left NOT UMINUS
  82. %right POWER
  83. %right DECR INCR
  84. %left INDIRECT
  85. %token LASTTOKEN /* must be last */
  86. %%
  87. program:
  88. pas { if (errorflag==0)
  89. winner = (Node *)stat3(PROGRAM, beginloc, $1, endloc); }
  90. | error { yyclearin; bracecheck(); ERROR "bailing out" SYNTAX; }
  91. ;
  92. and:
  93. AND | and NL
  94. ;
  95. bor:
  96. BOR | bor NL
  97. ;
  98. comma:
  99. ',' | comma NL
  100. ;
  101. do:
  102. DO | do NL
  103. ;
  104. else:
  105. ELSE | else NL
  106. ;
  107. for:
  108. FOR '(' opt_simple_stmt ';' opt_nl pattern ';' opt_nl opt_simple_stmt rparen {inloop++;} stmt
  109. { --inloop; $$ = stat4(FOR, $3, notnull($6), $9, $12); }
  110. | FOR '(' opt_simple_stmt ';' ';' opt_nl opt_simple_stmt rparen {inloop++;} stmt
  111. { --inloop; $$ = stat4(FOR, $3, NIL, $7, $10); }
  112. | FOR '(' varname IN varname rparen {inloop++;} stmt
  113. { --inloop; $$ = stat3(IN, $3, makearr($5), $8); }
  114. ;
  115. funcname:
  116. VAR { setfname($1); }
  117. | CALL { setfname($1); }
  118. ;
  119. if:
  120. IF '(' pattern rparen { $$ = notnull($3); }
  121. ;
  122. lbrace:
  123. '{' | lbrace NL
  124. ;
  125. nl:
  126. NL | nl NL
  127. ;
  128. opt_nl:
  129. /* empty */ { $$ = 0; }
  130. | nl
  131. ;
  132. opt_pst:
  133. /* empty */ { $$ = 0; }
  134. | pst
  135. ;
  136. opt_simple_stmt:
  137. /* empty */ { $$ = 0; }
  138. | simple_stmt
  139. ;
  140. pas:
  141. opt_pst { $$ = 0; }
  142. | opt_pst pa_stats opt_pst { $$ = $2; }
  143. ;
  144. pa_pat:
  145. pattern { $$ = notnull($1); }
  146. ;
  147. pa_stat:
  148. pa_pat { $$ = stat2(PASTAT, $1, stat2(PRINT, rectonode(), NIL)); }
  149. | pa_pat lbrace stmtlist '}' { $$ = stat2(PASTAT, $1, $3); }
  150. | pa_pat ',' pa_pat { $$ = pa2stat($1, $3, stat2(PRINT, rectonode(), NIL)); }
  151. | pa_pat ',' pa_pat lbrace stmtlist '}' { $$ = pa2stat($1, $3, $5); }
  152. | lbrace stmtlist '}' { $$ = stat2(PASTAT, NIL, $2); }
  153. | XBEGIN lbrace stmtlist '}'
  154. { beginloc = linkum(beginloc, $3); $$ = 0; }
  155. | XEND lbrace stmtlist '}'
  156. { endloc = linkum(endloc, $3); $$ = 0; }
  157. | FUNC funcname '(' varlist rparen {infunc++;} lbrace stmtlist '}'
  158. { infunc--; curfname=0; defn((Cell *)$2, $4, $8); $$ = 0; }
  159. ;
  160. pa_stats:
  161. pa_stat
  162. | pa_stats opt_pst pa_stat { $$ = linkum($1, $3); }
  163. ;
  164. patlist:
  165. pattern
  166. | patlist comma pattern { $$ = linkum($1, $3); }
  167. ;
  168. ppattern:
  169. var ASGNOP ppattern { $$ = op2($2, $1, $3); }
  170. | ppattern '?' ppattern ':' ppattern %prec '?'
  171. { $$ = op3(CONDEXPR, notnull($1), $3, $5); }
  172. | ppattern bor ppattern %prec BOR
  173. { $$ = op2(BOR, notnull($1), notnull($3)); }
  174. | ppattern and ppattern %prec AND
  175. { $$ = op2(AND, notnull($1), notnull($3)); }
  176. | ppattern MATCHOP reg_expr { $$ = op3($2, NIL, $1, (Node*)makedfa($3, 0)); }
  177. | ppattern MATCHOP ppattern
  178. { if (constnode($3))
  179. $$ = op3($2, NIL, $1, (Node*)makedfa(strnode($3), 0));
  180. else
  181. $$ = op3($2, (Node *)1, $1, $3); }
  182. | ppattern IN varname { $$ = op2(INTEST, $1, makearr($3)); }
  183. | '(' plist ')' IN varname { $$ = op2(INTEST, $2, makearr($5)); }
  184. | ppattern term %prec CAT { $$ = op2(CAT, $1, $2); }
  185. | re
  186. | term
  187. ;
  188. pattern:
  189. var ASGNOP pattern { $$ = op2($2, $1, $3); }
  190. | pattern '?' pattern ':' pattern %prec '?'
  191. { $$ = op3(CONDEXPR, notnull($1), $3, $5); }
  192. | pattern bor pattern %prec BOR
  193. { $$ = op2(BOR, notnull($1), notnull($3)); }
  194. | pattern and pattern %prec AND
  195. { $$ = op2(AND, notnull($1), notnull($3)); }
  196. | pattern EQ pattern { $$ = op2($2, $1, $3); }
  197. | pattern GE pattern { $$ = op2($2, $1, $3); }
  198. | pattern GT pattern { $$ = op2($2, $1, $3); }
  199. | pattern LE pattern { $$ = op2($2, $1, $3); }
  200. | pattern LT pattern { $$ = op2($2, $1, $3); }
  201. | pattern NE pattern { $$ = op2($2, $1, $3); }
  202. | pattern MATCHOP reg_expr { $$ = op3($2, NIL, $1, (Node*)makedfa($3, 0)); }
  203. | pattern MATCHOP pattern
  204. { if (constnode($3))
  205. $$ = op3($2, NIL, $1, (Node*)makedfa(strnode($3), 0));
  206. else
  207. $$ = op3($2, (Node *)1, $1, $3); }
  208. | pattern IN varname { $$ = op2(INTEST, $1, makearr($3)); }
  209. | '(' plist ')' IN varname { $$ = op2(INTEST, $2, makearr($5)); }
  210. | pattern '|' GETLINE var {
  211. if (safe) ERROR "cmd | getline is unsafe" SYNTAX;
  212. else $$ = op3(GETLINE, $4, (Node*)$2, $1); }
  213. | pattern '|' GETLINE {
  214. if (safe) ERROR "cmd | getline is unsafe" SYNTAX;
  215. else $$ = op3(GETLINE, (Node*)0, (Node*)$2, $1); }
  216. | pattern term %prec CAT { $$ = op2(CAT, $1, $2); }
  217. | re
  218. | term
  219. ;
  220. plist:
  221. pattern comma pattern { $$ = linkum($1, $3); }
  222. | plist comma pattern { $$ = linkum($1, $3); }
  223. ;
  224. pplist:
  225. ppattern
  226. | pplist comma ppattern { $$ = linkum($1, $3); }
  227. ;
  228. prarg:
  229. /* empty */ { $$ = rectonode(); }
  230. | pplist
  231. | '(' plist ')' { $$ = $2; }
  232. ;
  233. print:
  234. PRINT | PRINTF
  235. ;
  236. pst:
  237. NL | ';' | pst NL | pst ';'
  238. ;
  239. rbrace:
  240. '}' | rbrace NL
  241. ;
  242. re:
  243. reg_expr
  244. { $$ = op3(MATCH, NIL, rectonode(), (Node*)makedfa($1, 0)); }
  245. | NOT re { $$ = op1(NOT, notnull($2)); }
  246. ;
  247. reg_expr:
  248. '/' {startreg();} REGEXPR '/' { $$ = $3; }
  249. ;
  250. rparen:
  251. ')' | rparen NL
  252. ;
  253. simple_stmt:
  254. print prarg '|' term {
  255. if (safe) ERROR "print | is unsafe" SYNTAX;
  256. else $$ = stat3($1, $2, (Node *) $3, $4); }
  257. | print prarg APPEND term {
  258. if (safe) ERROR "print >> is unsafe" SYNTAX;
  259. else $$ = stat3($1, $2, (Node *) $3, $4); }
  260. | print prarg GT term {
  261. if (safe) ERROR "print > is unsafe" SYNTAX;
  262. else $$ = stat3($1, $2, (Node *) $3, $4); }
  263. | print prarg { $$ = stat3($1, $2, NIL, NIL); }
  264. | DELETE varname '[' patlist ']' { $$ = stat2(DELETE, makearr($2), $4); }
  265. | DELETE varname { $$ = stat2(DELETE, makearr($2), 0); }
  266. | pattern { $$ = exptostat($1); }
  267. | error { yyclearin; ERROR "illegal statement" SYNTAX; }
  268. ;
  269. st:
  270. nl
  271. | ';' opt_nl
  272. ;
  273. stmt:
  274. BREAK st { if (!inloop) ERROR "break illegal outside of loops" SYNTAX;
  275. $$ = stat1(BREAK, NIL); }
  276. | CLOSE pattern st { $$ = stat1(CLOSE, $2); }
  277. | CONTINUE st { if (!inloop) ERROR "continue illegal outside of loops" SYNTAX;
  278. $$ = stat1(CONTINUE, NIL); }
  279. | do {inloop++;} stmt {--inloop;} WHILE '(' pattern ')' st
  280. { $$ = stat2(DO, $3, notnull($7)); }
  281. | EXIT pattern st { $$ = stat1(EXIT, $2); }
  282. | EXIT st { $$ = stat1(EXIT, NIL); }
  283. | for
  284. | if stmt else stmt { $$ = stat3(IF, $1, $2, $4); }
  285. | if stmt { $$ = stat3(IF, $1, $2, NIL); }
  286. | lbrace stmtlist rbrace { $$ = $2; }
  287. | NEXT st { if (infunc)
  288. ERROR "next is illegal inside a function" SYNTAX;
  289. $$ = stat1(NEXT, NIL); }
  290. | NEXTFILE st { if (infunc)
  291. ERROR "nextfile is illegal inside a function" SYNTAX;
  292. $$ = stat1(NEXTFILE, NIL); }
  293. | RETURN pattern st { $$ = stat1(RETURN, $2); }
  294. | RETURN st { $$ = stat1(RETURN, NIL); }
  295. | simple_stmt st
  296. | while {inloop++;} stmt { --inloop; $$ = stat2(WHILE, $1, $3); }
  297. | ';' opt_nl { $$ = 0; }
  298. ;
  299. stmtlist:
  300. stmt
  301. | stmtlist stmt { $$ = linkum($1, $2); }
  302. ;
  303. subop:
  304. SUB | GSUB
  305. ;
  306. term:
  307. term '+' term { $$ = op2(ADD, $1, $3); }
  308. | term '-' term { $$ = op2(MINUS, $1, $3); }
  309. | term '*' term { $$ = op2(MULT, $1, $3); }
  310. | term '/' term { $$ = op2(DIVIDE, $1, $3); }
  311. | term '%' term { $$ = op2(MOD, $1, $3); }
  312. | term POWER term { $$ = op2(POWER, $1, $3); }
  313. | '-' term %prec UMINUS { $$ = op1(UMINUS, $2); }
  314. | '+' term %prec UMINUS { $$ = $2; }
  315. | NOT term %prec UMINUS { $$ = op1(NOT, notnull($2)); }
  316. | BLTIN '(' ')' { $$ = op2(BLTIN, (Node *) $1, rectonode()); }
  317. | BLTIN '(' patlist ')' { $$ = op2(BLTIN, (Node *) $1, $3); }
  318. | BLTIN { $$ = op2(BLTIN, (Node *) $1, rectonode()); }
  319. | CALL '(' ')' { $$ = op2(CALL, celltonode($1,CVAR), NIL); }
  320. | CALL '(' patlist ')' { $$ = op2(CALL, celltonode($1,CVAR), $3); }
  321. | DECR var { $$ = op1(PREDECR, $2); }
  322. | INCR var { $$ = op1(PREINCR, $2); }
  323. | var DECR { $$ = op1(POSTDECR, $1); }
  324. | var INCR { $$ = op1(POSTINCR, $1); }
  325. | GETLINE var LT term { $$ = op3(GETLINE, $2, (Node *)$3, $4); }
  326. | GETLINE LT term { $$ = op3(GETLINE, NIL, (Node *)$2, $3); }
  327. | GETLINE var { $$ = op3(GETLINE, $2, NIL, NIL); }
  328. | GETLINE { $$ = op3(GETLINE, NIL, NIL, NIL); }
  329. | INDEX '(' pattern comma pattern ')'
  330. { $$ = op2(INDEX, $3, $5); }
  331. | INDEX '(' pattern comma reg_expr ')'
  332. { ERROR "index() doesn't permit regular expressions" SYNTAX;
  333. $$ = op2(INDEX, $3, (Node*)$5); }
  334. | '(' pattern ')' { $$ = $2; }
  335. | MATCHFCN '(' pattern comma reg_expr ')'
  336. { $$ = op3(MATCHFCN, NIL, $3, (Node*)makedfa($5, 1)); }
  337. | MATCHFCN '(' pattern comma pattern ')'
  338. { if (constnode($5))
  339. $$ = op3(MATCHFCN, NIL, $3, (Node*)makedfa(strnode($5), 1));
  340. else
  341. $$ = op3(MATCHFCN, (Node *)1, $3, $5); }
  342. | NUMBER { $$ = celltonode($1, CCON); }
  343. | SPLIT '(' pattern comma varname comma pattern ')' /* string */
  344. { $$ = op4(SPLIT, $3, makearr($5), $7, (Node*)STRING); }
  345. | SPLIT '(' pattern comma varname comma reg_expr ')' /* const /regexp/ */
  346. { $$ = op4(SPLIT, $3, makearr($5), (Node*)makedfa($7, 1), (Node *)REGEXPR); }
  347. | SPLIT '(' pattern comma varname ')'
  348. { $$ = op4(SPLIT, $3, makearr($5), NIL, (Node*)STRING); } /* default */
  349. | SPRINTF '(' patlist ')' { $$ = op1($1, $3); }
  350. | STRING { $$ = celltonode($1, CCON); }
  351. | subop '(' reg_expr comma pattern ')'
  352. { $$ = op4($1, NIL, (Node*)makedfa($3, 1), $5, rectonode()); }
  353. | subop '(' pattern comma pattern ')'
  354. { if (constnode($3))
  355. $$ = op4($1, NIL, (Node*)makedfa(strnode($3), 1), $5, rectonode());
  356. else
  357. $$ = op4($1, (Node *)1, $3, $5, rectonode()); }
  358. | subop '(' reg_expr comma pattern comma var ')'
  359. { $$ = op4($1, NIL, (Node*)makedfa($3, 1), $5, $7); }
  360. | subop '(' pattern comma pattern comma var ')'
  361. { if (constnode($3))
  362. $$ = op4($1, NIL, (Node*)makedfa(strnode($3), 1), $5, $7);
  363. else
  364. $$ = op4($1, (Node *)1, $3, $5, $7); }
  365. | SUBSTR '(' pattern comma pattern comma pattern ')'
  366. { $$ = op3(SUBSTR, $3, $5, $7); }
  367. | SUBSTR '(' pattern comma pattern ')'
  368. { $$ = op3(SUBSTR, $3, $5, NIL); }
  369. | var
  370. ;
  371. var:
  372. varname
  373. | varname '[' patlist ']' { $$ = op2(ARRAY, makearr($1), $3); }
  374. | IVAR { $$ = op1(INDIRECT, celltonode($1, CVAR)); }
  375. | INDIRECT term { $$ = op1(INDIRECT, $2); }
  376. ;
  377. varlist:
  378. /* nothing */ { arglist = $$ = 0; }
  379. | VAR { arglist = $$ = celltonode($1,CVAR); }
  380. | varlist comma VAR {
  381. checkdup($1, $3);
  382. arglist = $$ = linkum($1,celltonode($3,CVAR)); }
  383. ;
  384. varname:
  385. VAR { $$ = celltonode($1, CVAR); }
  386. | ARG { $$ = op1(ARG, (Node *) $1); }
  387. | VARNF { $$ = op1(VARNF, (Node *) $1); }
  388. ;
  389. while:
  390. WHILE '(' pattern rparen { $$ = notnull($3); }
  391. ;
  392. %%
  393. void setfname(Cell *p)
  394. {
  395. if (isarr(p))
  396. ERROR "%s is an array, not a function", p->nval SYNTAX;
  397. else if (isfcn(p))
  398. ERROR "you can't define function %s more than once", p->nval SYNTAX;
  399. curfname = p->nval;
  400. }
  401. int constnode(Node *p)
  402. {
  403. return isvalue(p) && ((Cell *) (p->narg[0]))->csub == CCON;
  404. }
  405. char *strnode(Node *p)
  406. {
  407. return ((Cell *)(p->narg[0]))->sval;
  408. }
  409. Node *notnull(Node *n)
  410. {
  411. switch (n->nobj) {
  412. case LE: case LT: case EQ: case NE: case GT: case GE:
  413. case BOR: case AND: case NOT:
  414. return n;
  415. default:
  416. return op2(NE, n, nullnode);
  417. }
  418. }
  419. void checkdup(Node *vl, Cell *cp) /* check if name already in list */
  420. {
  421. char *s = cp->nval;
  422. for ( ; vl; vl = vl->nnext) {
  423. if (strcmp(s, ((Cell *)(vl->narg[0]))->nval) == 0) {
  424. ERROR "duplicate argument %s", s SYNTAX;
  425. break;
  426. }
  427. }
  428. }