| [9] | 1 | /**
 | 
|---|
 | 2 |  * Copyright (c) 1985 Sun Microsystems, Inc.
 | 
|---|
 | 3 |  * Copyright (c) 1980 The Regents of the University of California.
 | 
|---|
 | 4 |  * Copyright (c) 1976 Board of Trustees of the University of Illinois.
 | 
|---|
 | 5 |  * All rights reserved.
 | 
|---|
 | 6 |  *
 | 
|---|
 | 7 |  * Redistribution and use in source and binary forms are permitted
 | 
|---|
 | 8 |  * provided that the above copyright notice and this paragraph are
 | 
|---|
 | 9 |  * duplicated in all such forms and that any documentation,
 | 
|---|
 | 10 |  * advertising materials, and other materials related to such
 | 
|---|
 | 11 |  * distribution and use acknowledge that the software was developed
 | 
|---|
 | 12 |  * by the University of California, Berkeley, the University of Illinois,
 | 
|---|
 | 13 |  * Urbana, and Sun Microsystems, Inc.  The name of either University
 | 
|---|
 | 14 |  * or Sun Microsystems may not be used to endorse or promote products
 | 
|---|
 | 15 |  * derived from this software without specific prior written permission.
 | 
|---|
 | 16 |  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 | 
|---|
 | 17 |  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 | 
|---|
 | 18 |  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 | 
|---|
 | 19 |  */
 | 
|---|
 | 20 | 
 | 
|---|
 | 21 | #define PUBLIC  extern
 | 
|---|
 | 22 | #include "./globs.h"
 | 
|---|
 | 23 | #include "./codes.h"
 | 
|---|
 | 24 | #include "proto.h"
 | 
|---|
 | 25 | 
 | 
|---|
 | 26 | 
 | 
|---|
 | 27 | 
 | 
|---|
 | 28 | 
 | 
|---|
 | 29 | void parse(tk)
 | 
|---|
 | 30 |    int             tk;                  /* the code for the construct
 | 
|---|
 | 31 |                                            scanned */
 | 
|---|
 | 32 | {
 | 
|---|
 | 33 |    int             i;
 | 
|---|
 | 34 | 
 | 
|---|
 | 35 | #ifdef debug
 | 
|---|
 | 36 |    printf("%2d - %s\n", tk, token);
 | 
|---|
 | 37 | #endif
 | 
|---|
 | 38 | 
 | 
|---|
 | 39 |    while (ps.p_stack[ps.tos] == ifhead && tk != elselit)
 | 
|---|
 | 40 |    {
 | 
|---|
 | 41 |       /* true if we have an if without an else */
 | 
|---|
 | 42 |       ps.p_stack[ps.tos] = stmt;        /* apply the if(..) stmt ::=
 | 
|---|
 | 43 |                                            stmt reduction */
 | 
|---|
 | 44 |       reduce();                         /* see if this allows any
 | 
|---|
 | 45 |                                            reduction */
 | 
|---|
 | 46 |    }
 | 
|---|
 | 47 | 
 | 
|---|
 | 48 | 
 | 
|---|
 | 49 |    switch (tk)
 | 
|---|
 | 50 |    {                                    /* go on and figure out what to
 | 
|---|
 | 51 |                                            do with the input */
 | 
|---|
 | 52 | 
 | 
|---|
 | 53 |    case decl:                           /* scanned a declaration word */
 | 
|---|
 | 54 |       ps.search_brace = btype_2;
 | 
|---|
 | 55 |       /* indicate that following brace should be on same line */
 | 
|---|
 | 56 |       if (ps.p_stack[ps.tos] != decl)
 | 
|---|
 | 57 |       {                                 /* only put one declaration
 | 
|---|
 | 58 |                                            onto stack */
 | 
|---|
 | 59 |          break_comma = true;            /* while in declaration,
 | 
|---|
 | 60 |                                            newline should be forced
 | 
|---|
 | 61 |                                            after comma */
 | 
|---|
 | 62 |          ps.p_stack[++ps.tos] = decl;
 | 
|---|
 | 63 |          ps.il[ps.tos] = ps.i_l_follow;
 | 
|---|
 | 64 | 
 | 
|---|
 | 65 |          if (ps.ljust_decl)
 | 
|---|
 | 66 |          {                              /* only do if we want left
 | 
|---|
 | 67 |                                            justified declarations */
 | 
|---|
 | 68 |             ps.ind_level = 0;
 | 
|---|
 | 69 |             for (i = ps.tos - 1; i > 0; --i)
 | 
|---|
 | 70 |                if (ps.p_stack[i] == decl)
 | 
|---|
 | 71 |                   ++ps.ind_level;       /* indentation is number of
 | 
|---|
 | 72 |                                            declaration levels deep we
 | 
|---|
 | 73 |                                            are */
 | 
|---|
 | 74 |             ps.i_l_follow = ps.ind_level;
 | 
|---|
 | 75 |          }
 | 
|---|
 | 76 |       }
 | 
|---|
 | 77 |       break;
 | 
|---|
 | 78 | 
 | 
|---|
 | 79 |    case ifstmt:                 /* scanned if (...) */
 | 
|---|
 | 80 |       if (ps.p_stack[ps.tos] == elsehead && ps.else_if) /* "else if ..." */
 | 
|---|
 | 81 |          ps.i_l_follow = ps.il[ps.tos];
 | 
|---|
 | 82 |    case dolit:                          /* 'do' */
 | 
|---|
 | 83 |    case forstmt:                        /* for (...) */
 | 
|---|
 | 84 |       ps.p_stack[++ps.tos] = tk;
 | 
|---|
 | 85 |       ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
 | 
|---|
 | 86 |       ++ps.i_l_follow;                  /* subsequent statements should
 | 
|---|
 | 87 |                                            be indented 1 */
 | 
|---|
 | 88 |       ps.search_brace = btype_2;
 | 
|---|
 | 89 |       break;
 | 
|---|
 | 90 | 
 | 
|---|
 | 91 |    case lbrace:                 /* scanned { */
 | 
|---|
 | 92 |       break_comma = false;              /* don't break comma in an
 | 
|---|
 | 93 |                                            initial list */
 | 
|---|
 | 94 |       if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl
 | 
|---|
 | 95 |           || ps.p_stack[ps.tos] == stmtl)
 | 
|---|
 | 96 |          ++ps.i_l_follow;               /* it is a random, isolated
 | 
|---|
 | 97 |                                            stmt group or a declaration */
 | 
|---|
 | 98 |       else
 | 
|---|
 | 99 |       {
 | 
|---|
 | 100 |          if (s_code == e_code)
 | 
|---|
 | 101 |          {
 | 
|---|
 | 102 |             /* only do this if there is nothing on the line */
 | 
|---|
 | 103 |             --ps.ind_level;
 | 
|---|
 | 104 |             /* it is a group as part of a while, for, etc. */
 | 
|---|
 | 105 |             if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1)
 | 
|---|
 | 106 |                --ps.ind_level;
 | 
|---|
 | 107 |             /* for a switch, brace should be two levels out from the
 | 
|---|
 | 108 |                code */
 | 
|---|
 | 109 |          }
 | 
|---|
 | 110 |       }
 | 
|---|
 | 111 | 
 | 
|---|
 | 112 |       ps.p_stack[++ps.tos] = lbrace;
 | 
|---|
 | 113 |       ps.il[ps.tos] = ps.ind_level;
 | 
|---|
 | 114 |       ps.p_stack[++ps.tos] = stmt;
 | 
|---|
 | 115 |       /* allow null stmt between braces */
 | 
|---|
 | 116 |       ps.il[ps.tos] = ps.i_l_follow;
 | 
|---|
 | 117 |       break;
 | 
|---|
 | 118 | 
 | 
|---|
 | 119 |    case whilestmt:                      /* scanned while (...) */
 | 
|---|
 | 120 |       if (ps.p_stack[ps.tos] == dohead)
 | 
|---|
 | 121 |       {
 | 
|---|
 | 122 |          /* it is matched with do stmt */
 | 
|---|
 | 123 |          ps.ind_level = ps.i_l_follow = ps.il[ps.tos];
 | 
|---|
 | 124 |          ps.p_stack[++ps.tos] = whilestmt;
 | 
|---|
 | 125 |          ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
 | 
|---|
 | 126 |       } else
 | 
|---|
 | 127 |       {                                 /* it is a while loop */
 | 
|---|
 | 128 |          ps.p_stack[++ps.tos] = whilestmt;
 | 
|---|
 | 129 |          ps.il[ps.tos] = ps.i_l_follow;
 | 
|---|
 | 130 |          ++ps.i_l_follow;
 | 
|---|
 | 131 |          ps.search_brace = btype_2;
 | 
|---|
 | 132 |       }
 | 
|---|
 | 133 | 
 | 
|---|
 | 134 |       break;
 | 
|---|
 | 135 | 
 | 
|---|
 | 136 |    case elselit:                        /* scanned an else */
 | 
|---|
 | 137 | 
 | 
|---|
 | 138 |       if (ps.p_stack[ps.tos] != ifhead)
 | 
|---|
 | 139 |          diag(1, "Unmatched 'else'");
 | 
|---|
 | 140 |       else
 | 
|---|
 | 141 |       {
 | 
|---|
 | 142 |          ps.ind_level = ps.il[ps.tos];  /* indentation for else should
 | 
|---|
 | 143 |                                            be same as for if */
 | 
|---|
 | 144 |          ps.i_l_follow = ps.ind_level + 1;      /* everything following
 | 
|---|
 | 145 |                                                    should be in 1 level */
 | 
|---|
 | 146 |          ps.p_stack[ps.tos] = elsehead;
 | 
|---|
 | 147 |          /* remember if with else */
 | 
|---|
 | 148 |          ps.search_brace = btype_2 | ps.else_if;
 | 
|---|
 | 149 |       }
 | 
|---|
 | 150 |       break;
 | 
|---|
 | 151 | 
 | 
|---|
 | 152 |    case rbrace:                 /* scanned a } */
 | 
|---|
 | 153 |       /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */
 | 
|---|
 | 154 |       if (ps.p_stack[ps.tos - 1] == lbrace)
 | 
|---|
 | 155 |       {
 | 
|---|
 | 156 |          ps.ind_level = ps.i_l_follow = ps.il[--ps.tos];
 | 
|---|
 | 157 |          ps.p_stack[ps.tos] = stmt;
 | 
|---|
 | 158 |       } else
 | 
|---|
 | 159 |          diag(1, "Stmt nesting error.");
 | 
|---|
 | 160 |       break;
 | 
|---|
 | 161 | 
 | 
|---|
 | 162 |    case swstmt:                 /* had switch (...) */
 | 
|---|
 | 163 |       ps.p_stack[++ps.tos] = swstmt;
 | 
|---|
 | 164 |       ps.cstk[ps.tos] = case_ind;
 | 
|---|
 | 165 |       /* save current case indent level */
 | 
|---|
 | 166 |       ps.il[ps.tos] = ps.i_l_follow;
 | 
|---|
 | 167 |       case_ind = ps.i_l_follow + ps.case_indent;        /* cases should be one
 | 
|---|
 | 168 |                                                            level down from
 | 
|---|
 | 169 |                                                            switch */
 | 
|---|
 | 170 |       ps.i_l_follow += ps.case_indent + 1;      /* statements should be
 | 
|---|
 | 171 |                                                    two levels in */
 | 
|---|
 | 172 |       ps.search_brace = btype_2;
 | 
|---|
 | 173 |       break;
 | 
|---|
 | 174 | 
 | 
|---|
 | 175 |    case semicolon:                      /* this indicates a simple stmt */
 | 
|---|
 | 176 |       break_comma = false;              /* turn off flag to break after
 | 
|---|
 | 177 |                                            commas in a declaration */
 | 
|---|
 | 178 |       ps.p_stack[++ps.tos] = stmt;
 | 
|---|
 | 179 |       ps.il[ps.tos] = ps.ind_level;
 | 
|---|
 | 180 |       break;
 | 
|---|
 | 181 | 
 | 
|---|
 | 182 |    default:                             /* this is an error */
 | 
|---|
 | 183 |       diag(1, "Unknown code to parser");
 | 
|---|
 | 184 |       return;
 | 
|---|
 | 185 | 
 | 
|---|
 | 186 | 
 | 
|---|
 | 187 |    }                                    /* end of switch */
 | 
|---|
 | 188 | 
 | 
|---|
 | 189 |    reduce();                            /* see if any reduction can be
 | 
|---|
 | 190 |                                            done */
 | 
|---|
 | 191 | 
 | 
|---|
 | 192 | #ifdef debug
 | 
|---|
 | 193 |    for (i = 1; i <= ps.tos; ++i)
 | 
|---|
 | 194 |       printf("(%d %d)", ps.p_stack[i], ps.il[i]);
 | 
|---|
 | 195 |    printf("\n");
 | 
|---|
 | 196 | #endif
 | 
|---|
 | 197 | 
 | 
|---|
 | 198 |    return;
 | 
|---|
 | 199 | }
 | 
|---|
 | 200 | 
 | 
|---|
 | 201 | /*
 | 
|---|
 | 202 |  * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
 | 
|---|
 | 203 |  *
 | 
|---|
 | 204 |  * All rights reserved
 | 
|---|
 | 205 |  *
 | 
|---|
 | 206 |  *
 | 
|---|
 | 207 |  * NAME: reduce
 | 
|---|
 | 208 |  *
 | 
|---|
 | 209 |  * FUNCTION: Implements the reduce part of the parsing algorithm
 | 
|---|
 | 210 |  *
 | 
|---|
 | 211 |  * ALGORITHM: The following reductions are done.  Reductions are repeated until
 | 
|---|
 | 212 |  * no more are possible.
 | 
|---|
 | 213 |  *
 | 
|---|
 | 214 |  * Old TOS              New TOS <stmt> <stmt>   <stmtl> <stmtl> <stmt>  <stmtl> do
 | 
|---|
 | 215 |  * <stmt>       "dostmt" if <stmt>      "ifstmt" switch <stmt>  <stmt> decl
 | 
|---|
 | 216 |  * <stmt>       <stmt> "ifelse" <stmt>  <stmt> for <stmt>       <stmt> while
 | 
|---|
 | 217 |  * <stmt>       <stmt> "dostmt" while   <stmt>
 | 
|---|
 | 218 |  *
 | 
|---|
 | 219 |  * On each reduction, ps.i_l_follow (the indentation for the following line) is
 | 
|---|
 | 220 |  * set to the indentation level associated with the old TOS.
 | 
|---|
 | 221 |  *
 | 
|---|
 | 222 |  * PARAMETERS: None
 | 
|---|
 | 223 |  *
 | 
|---|
 | 224 |  * RETURNS: Nothing
 | 
|---|
 | 225 |  *
 | 
|---|
 | 226 |  * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos =
 | 
|---|
 | 227 |  *
 | 
|---|
 | 228 |  * CALLS: None
 | 
|---|
 | 229 |  *
 | 
|---|
 | 230 |  * CALLED BY: parse
 | 
|---|
 | 231 |  *
 | 
|---|
 | 232 |  * HISTORY: initial coding      November 1976   D A Willcox of CAC
 | 
|---|
 | 233 |  *
 | 
|---|
 | 234 |  */ | 
|---|
 | 235 | 
 | 
|---|
 | 236 | /*----------------------------------------------*\
 | 
|---|
 | 237 | |   REDUCTION PHASE                                 |
 | 
|---|
 | 238 | \*----------------------------------------------*/
 | 
|---|
 | 239 | void reduce()
 | 
|---|
 | 240 | {
 | 
|---|
 | 241 | 
 | 
|---|
 | 242 |    register int    i;
 | 
|---|
 | 243 | 
 | 
|---|
 | 244 |    for (;;)
 | 
|---|
 | 245 |    {                                    /* keep looping until there is
 | 
|---|
 | 246 |                                            nothing left to reduce */
 | 
|---|
 | 247 | 
 | 
|---|
 | 248 |       switch (ps.p_stack[ps.tos])
 | 
|---|
 | 249 |       {
 | 
|---|
 | 250 | 
 | 
|---|
 | 251 |       case stmt:
 | 
|---|
 | 252 |          switch (ps.p_stack[ps.tos - 1])
 | 
|---|
 | 253 |          {
 | 
|---|
 | 254 | 
 | 
|---|
 | 255 |          case stmt:
 | 
|---|
 | 256 |          case stmtl:
 | 
|---|
 | 257 |             /* stmtl stmt or stmt stmt */
 | 
|---|
 | 258 |             ps.p_stack[--ps.tos] = stmtl;
 | 
|---|
 | 259 |             break;
 | 
|---|
 | 260 | 
 | 
|---|
 | 261 |          case dolit:                    /* <do> <stmt> */
 | 
|---|
 | 262 |             ps.p_stack[--ps.tos] = dohead;
 | 
|---|
 | 263 |             ps.i_l_follow = ps.il[ps.tos];
 | 
|---|
 | 264 |             break;
 | 
|---|
 | 265 | 
 | 
|---|
 | 266 |          case ifstmt:
 | 
|---|
 | 267 |             /* <if> <stmt> */
 | 
|---|
 | 268 |             ps.p_stack[--ps.tos] = ifhead;
 | 
|---|
 | 269 |             for (i = ps.tos - 1;
 | 
|---|
 | 270 |                  (
 | 
|---|
 | 271 |                   ps.p_stack[i] != stmt
 | 
|---|
 | 272 |                   &&
 | 
|---|
 | 273 |                   ps.p_stack[i] != stmtl
 | 
|---|
 | 274 |                   &&
 | 
|---|
 | 275 |                   ps.p_stack[i] != lbrace
 | 
|---|
 | 276 |                   );
 | 
|---|
 | 277 |                  --i);
 | 
|---|
 | 278 |             ps.i_l_follow = ps.il[i];
 | 
|---|
 | 279 |             /* for the time being, we will assume that there is no else
 | 
|---|
 | 280 |                on this if, and set the indentation level accordingly.
 | 
|---|
 | 281 |                If an else is scanned, it will be fixed up later */
 | 
|---|
 | 282 |             break;
 | 
|---|
 | 283 | 
 | 
|---|
 | 284 |          case swstmt:
 | 
|---|
 | 285 |             /* <switch> <stmt> */
 | 
|---|
 | 286 |             case_ind = ps.cstk[ps.tos - 1];
 | 
|---|
 | 287 | 
 | 
|---|
 | 288 |          case decl:                     /* finish of a declaration */
 | 
|---|
 | 289 |          case elsehead:
 | 
|---|
 | 290 |             /* <<if> <stmt> else> <stmt> */
 | 
|---|
 | 291 |          case forstmt:
 | 
|---|
 | 292 |             /* <for> <stmt> */
 | 
|---|
 | 293 |          case whilestmt:
 | 
|---|
 | 294 |             /* <while> <stmt> */
 | 
|---|
 | 295 |             ps.p_stack[--ps.tos] = stmt;
 | 
|---|
 | 296 |             ps.i_l_follow = ps.il[ps.tos];
 | 
|---|
 | 297 |             break;
 | 
|---|
 | 298 | 
 | 
|---|
 | 299 |          default:                       /* <anything else> <stmt> */
 | 
|---|
 | 300 |             return;
 | 
|---|
 | 301 | 
 | 
|---|
 | 302 |          }                              /* end of section for <stmt> on
 | 
|---|
 | 303 |                                            top of stack */
 | 
|---|
 | 304 |          break;
 | 
|---|
 | 305 | 
 | 
|---|
 | 306 |       case whilestmt:                   /* while (...) on top */
 | 
|---|
 | 307 |          if (ps.p_stack[ps.tos - 1] == dohead)
 | 
|---|
 | 308 |          {
 | 
|---|
 | 309 |             /* it is termination of a do while */
 | 
|---|
 | 310 |             ps.p_stack[--ps.tos] = stmt;
 | 
|---|
 | 311 |             break;
 | 
|---|
 | 312 |          } else
 | 
|---|
 | 313 |             return;
 | 
|---|
 | 314 | 
 | 
|---|
 | 315 |       default:                          /* anything else on top */
 | 
|---|
 | 316 |          return;
 | 
|---|
 | 317 | 
 | 
|---|
 | 318 |       }
 | 
|---|
 | 319 |    }
 | 
|---|
 | 320 | }
 | 
|---|