1*21971Sdist /* 2*21971Sdist * Copyright (c) 1980 Regents of the University of California. 3*21971Sdist * All rights reserved. The Berkeley software License Agreement 4*21971Sdist * specifies the terms and conditions for redistribution. 5*21971Sdist */ 68805Smckusick 7*21971Sdist #ifndef lint 8*21971Sdist static char sccsid[] = "@(#)parse.c 5.1 (Berkeley) 06/04/85"; 9*21971Sdist #endif not lint 10*21971Sdist 118805Smckusick /* 128805Smckusick 138805Smckusick Copyright (C) 1976 148805Smckusick by the 158805Smckusick Board of Trustees 168805Smckusick of the 178805Smckusick University of Illinois 188805Smckusick 198805Smckusick All rights reserved 208805Smckusick 218805Smckusick 228805Smckusick FILE NAME: 238805Smckusick parse.c 248805Smckusick 258805Smckusick PURPOSE: 268805Smckusick Contains the routines which keep track of the parse stack. 278805Smckusick 288805Smckusick GLOBALS: 298805Smckusick p_stack = The parse stack, set by both routines 308805Smckusick il = Stack of indentation levels, set by parse 318805Smckusick cstk = Stack of case statement indentation levels, set by parse 328805Smckusick tos = Pointer to top of stack, set by both routines. 338805Smckusick 348805Smckusick FUNCTIONS: 358805Smckusick parse 368805Smckusick reduce 378805Smckusick */ 388805Smckusick /* 398805Smckusick 408805Smckusick Copyright (C) 1976 418805Smckusick by the 428805Smckusick Board of Trustees 438805Smckusick of the 448805Smckusick University of Illinois 458805Smckusick 468805Smckusick All rights reserved 478805Smckusick 488805Smckusick 498805Smckusick NAME: 508805Smckusick parse 518805Smckusick 528805Smckusick FUNCTION: 538805Smckusick Parse is given one input which is a "maxi token" just scanned from 548805Smckusick input. Maxi tokens are signifigant constructs such as else, {, do, 558805Smckusick if (...), etc. Parse works with reduce to maintain a parse stack 568805Smckusick of these constructs. Parse is responsible for the "shift" portion 578805Smckusick of the parse algorithm, and reduce handles the "reduce" portion. 588805Smckusick 598805Smckusick ALGORITHM: 608805Smckusick 1) If there is "ifstmt" on the stack and input is anything other than 618805Smckusick an else, then change the top of stack (TOS) to <stmt>. Do a reduce. 628805Smckusick 2) Use a switch statement to implement the following shift operations: 638805Smckusick 648805Smckusick TOS___ Input_____ Stack_____ Note____ 658805Smckusick decl decl nothing 668805Smckusick anything else decl decl 678805Smckusick "dostmt" while (..) Change TOS to <stmt> 688805Smckusick anything else while (..) while 698805Smckusick "ifstmt" else Change TOS to "ifelse" 708805Smckusick { <stmtl> } Change { <stmtl> 718805Smckusick to <stmtl> 728805Smckusick switch (..) switch 738805Smckusick do do 748805Smckusick for(..) for 758805Smckusick ; <stmt> 768805Smckusick { { <stmt> 778805Smckusick 788805Smckusick PARAMETERS: 798805Smckusick tk An integer code for the maxi token scanned 808805Smckusick 818805Smckusick RETURNS: 828805Smckusick Nothing 838805Smckusick 848805Smckusick GLOBALS: 858805Smckusick break_comma = Set to true when in a declaration but not initialization 868805Smckusick btype_2 878805Smckusick case_ind = 888805Smckusick cstk = 898805Smckusick i_l_follow = 908805Smckusick il = Stack of indentation levels 918805Smckusick ind_level = 928805Smckusick p_stack = Stack of token codes 938805Smckusick search_brace = Set to true if we must look for possibility of moving a 948805Smckusick brace 958805Smckusick tos = Pointer to top of p_stack, il, and cstk 968805Smckusick 978805Smckusick CALLS: 988805Smckusick printf (lib) 998805Smckusick reduce 1008805Smckusick 1018805Smckusick CALLED BY: 1028805Smckusick main 1038805Smckusick 1048805Smckusick HISTORY: 1058805Smckusick initial coding November 1976 D A Willcox of CAC 1068805Smckusick 1078805Smckusick */ 1088805Smckusick 1098805Smckusick #include "./indent_globs.h"; 1108805Smckusick #include "./indent_codes.h"; 1118805Smckusick 1128805Smckusick 1138805Smckusick int p_stack[50] = stmt; 1148805Smckusick /* this is the parser's stack */ 1158805Smckusick int il[50]; /* this stack stores indentation levels */ 1168805Smckusick int cstk[50]; /* used to store case stmt indentation levels */ 1178805Smckusick int tos = 0; /* pointer to top of stack */ 1188805Smckusick 1198805Smckusick 1208805Smckusick parse (tk) 1218805Smckusick int tk; /* the code for the construct scanned */ 1228805Smckusick { 1238805Smckusick int i; 1248805Smckusick 1258805Smckusick #ifdef debug 1268805Smckusick printf ("%2d - %s\n", tk, token); 1278805Smckusick #endif 1288805Smckusick while (p_stack[tos] == ifhead && tk != elselit) { 1298805Smckusick /* true if we have an if without an else */ 1308805Smckusick p_stack[tos] = stmt; /* apply the if(..) stmt ::= stmt reduction */ 1318805Smckusick reduce (); /* see if this allows any reduction */ 1328805Smckusick } 1338805Smckusick 1348805Smckusick 1358805Smckusick switch (tk) { /* go on and figure out what to do with the 1368805Smckusick input */ 1378805Smckusick 1388805Smckusick case decl: /* scanned a declaration word */ 1398805Smckusick search_brace = btype_2; 1408805Smckusick /* indicate that following brace should be on same line */ 1418805Smckusick if (p_stack[tos] != decl) { 1428805Smckusick /* only put one declaration onto stack */ 1438805Smckusick break_comma = true; 1448805Smckusick /* while in declaration, newline should be forced after comma */ 1458805Smckusick p_stack[++tos] = decl; 1468805Smckusick il[tos] = i_l_follow; 1478805Smckusick 1488805Smckusick if (ljust_decl) { 1498805Smckusick /* only do if we want left justified declarations */ 1508805Smckusick ind_level = 0; 1518805Smckusick for (i = tos - 1; i > 0; --i) 1528805Smckusick if (p_stack[i] == decl) 1538805Smckusick ++ind_level; 1548805Smckusick /* indentation is number of declaration levels deep we are */ 1558805Smckusick i_l_follow = ind_level; 1568805Smckusick } 1578805Smckusick } 1588805Smckusick break; 1598805Smckusick 1608805Smckusick case ifstmt: /* scanned if (...) */ 1618805Smckusick case dolit: /* 'do' */ 1628805Smckusick case forstmt: /* for (...) */ 1638805Smckusick p_stack[++tos] = tk; 1648805Smckusick il[tos] = ind_level = i_l_follow; 1658805Smckusick ++i_l_follow; /* subsequent statements should be indented 1 */ 1668805Smckusick search_brace = btype_2; 1678805Smckusick break; 1688805Smckusick 1698805Smckusick case lbrace: /* scanned { */ 1708805Smckusick break_comma = false; 1718805Smckusick /* don't break comma in an initial list */ 1728805Smckusick if (p_stack[tos] == stmt || p_stack[tos] == decl 1738805Smckusick || p_stack[tos] == stmtl) 1748805Smckusick ++i_l_follow; /* it is a random, isolated stmt group or a 1758805Smckusick declaration */ 1768805Smckusick else { 1778805Smckusick if (s_code == e_code) { 1788805Smckusick /* only do this if there is nothing on the line */ 1798805Smckusick --ind_level; 1808805Smckusick /* it is a group as part of a while, for, etc. */ 1818805Smckusick if (p_stack[tos] == swstmt) 1828805Smckusick --ind_level; 1838805Smckusick /* for a switch, brace should be two levels out from the code 1848805Smckusick */ 1858805Smckusick } 1868805Smckusick } 1878805Smckusick 1888805Smckusick p_stack[++tos] = lbrace; 1898805Smckusick il[tos] = ind_level; 1908805Smckusick p_stack[++tos] = stmt; 1918805Smckusick /* allow null stmt between braces */ 1928805Smckusick il[tos] = i_l_follow; 1938805Smckusick break; 1948805Smckusick 1958805Smckusick case whilestmt: /* scanned while (...) */ 1968805Smckusick if (p_stack[tos] == dohead) { 1978805Smckusick /* it is matched with do stmt */ 1988805Smckusick ind_level = i_l_follow = il[tos]; 1998805Smckusick p_stack[++tos] = whilestmt; 2008805Smckusick il[tos] = ind_level = i_l_follow; 2018805Smckusick } 2028805Smckusick else { /* it is a while loop */ 2038805Smckusick p_stack[++tos] = whilestmt; 2048805Smckusick il[tos] = i_l_follow; 2058805Smckusick ++i_l_follow; 2068805Smckusick search_brace = btype_2; 2078805Smckusick } 2088805Smckusick 2098805Smckusick break; 2108805Smckusick 2118805Smckusick case elselit: /* scanned an else */ 2128805Smckusick 2138805Smckusick if (p_stack[tos] != ifhead) { 2148805Smckusick printf ("%d: Unmatched else\n", line_no); 2158805Smckusick } 2168805Smckusick else { 2178805Smckusick ind_level = il[tos]; 2188805Smckusick /* indentation for else should be same as for if */ 2198805Smckusick i_l_follow = ind_level + 1; 2208805Smckusick /* everything following should be in 1 level */ 2218805Smckusick p_stack[tos] = elsehead; 2228805Smckusick /* remember if with else */ 2238805Smckusick search_brace = btype_2; 2248805Smckusick } 2258805Smckusick 2268805Smckusick break; 2278805Smckusick 2288805Smckusick case rbrace: /* scanned a } */ 2298805Smckusick /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */ 2308805Smckusick if (p_stack[tos - 1] == lbrace) { 2318805Smckusick ind_level = i_l_follow = il[--tos]; 2328805Smckusick p_stack[tos] = stmt; 2338805Smckusick } 2348805Smckusick else { 2358805Smckusick printf ("%d: Stmt nesting error\n", line_no); 2368805Smckusick } 2378805Smckusick 2388805Smckusick break; 2398805Smckusick 2408805Smckusick case swstmt: /* had switch (...) */ 2418805Smckusick p_stack[++tos] = swstmt; 2428805Smckusick cstk[tos] = case_ind; 2438805Smckusick /* save current case indent level */ 2448805Smckusick il[tos] = i_l_follow; 2458805Smckusick case_ind = i_l_follow + 1; 2468805Smckusick /* cases should be one level down from switch */ 2478805Smckusick i_l_follow + = 2; /* statements should be two levels in */ 2488805Smckusick search_brace = btype_2; 2498805Smckusick break; 2508805Smckusick 2518805Smckusick case semicolon: /* this indicates a simple stmt */ 2528805Smckusick break_comma = false; 2538805Smckusick /* turn off flag to break after commas in a declaration */ 2548805Smckusick p_stack[++tos] = stmt; 2558805Smckusick il[tos] = ind_level; 2568805Smckusick break; 2578805Smckusick 2588805Smckusick default: /* this is an error */ 2598805Smckusick printf ("%d: Unknown code to parser - %d\n", line_no, tk); 2608805Smckusick return; 2618805Smckusick 2628805Smckusick 2638805Smckusick } /* end of switch */ 2648805Smckusick 2658805Smckusick reduce (); /* see if any reduction can be done */ 2668805Smckusick #ifdef debug 2678805Smckusick for (i = 1; i <= tos; ++i) 2688805Smckusick printf ("(%d %d)", p_stack[i], il[i]); 2698805Smckusick printf ("\n"); 2708805Smckusick #endif 2718805Smckusick return; 2728805Smckusick } 2738805Smckusick /* 2748805Smckusick 2758805Smckusick Copyright (C) 1976 2768805Smckusick by the 2778805Smckusick Board of Trustees 2788805Smckusick of the 2798805Smckusick University of Illinois 2808805Smckusick 2818805Smckusick All rights reserved 2828805Smckusick 2838805Smckusick 2848805Smckusick NAME: 2858805Smckusick reduce 2868805Smckusick 2878805Smckusick FUNCTION: 2888805Smckusick Implements the reduce part of the parsing algorithm 2898805Smckusick 2908805Smckusick ALGORITHM: 2918805Smckusick The following reductions are done. Reductions are repeated until no 2928805Smckusick more are possible. 2938805Smckusick 2948805Smckusick Old___ TOS___ New___ TOS___ 2958805Smckusick <stmt> <stmt> <stmtl> 2968805Smckusick <stmtl> <stmt> <stmtl> 2978805Smckusick do <stmt> "dostmt" 2988805Smckusick if <stmt> "ifstmt" 2998805Smckusick switch <stmt> <stmt> 3008805Smckusick decl <stmt> <stmt> 3018805Smckusick "ifelse" <stmt> <stmt> 3028805Smckusick for <stmt> <stmt> 3038805Smckusick while <stmt> <stmt> 3048805Smckusick "dostmt" while <stmt> 3058805Smckusick 3068805Smckusick On each reduction, i_l_follow (the indentation for the following line) 3078805Smckusick is set to the indentation level associated with the old TOS. 3088805Smckusick 3098805Smckusick PARAMETERS: 3108805Smckusick None 3118805Smckusick 3128805Smckusick RETURNS: 3138805Smckusick Nothing 3148805Smckusick 3158805Smckusick GLOBALS: 3168805Smckusick cstk 3178805Smckusick i_l_follow = 3188805Smckusick il 3198805Smckusick p_stack = 3208805Smckusick tos = 3218805Smckusick 3228805Smckusick CALLS: 3238805Smckusick None 3248805Smckusick 3258805Smckusick CALLED BY: 3268805Smckusick parse 3278805Smckusick 3288805Smckusick HISTORY: 3298805Smckusick initial coding November 1976 D A Willcox of CAC 3308805Smckusick 3318805Smckusick */ 3328805Smckusick /*----------------------------------------------*\ 3338805Smckusick | REDUCTION PHASE 3348805Smckusick \*----------------------------------------------*/ 3358805Smckusick reduce () { 3368805Smckusick 3378805Smckusick register int i; 3388805Smckusick /* local looping variable */ 3398805Smckusick 3408805Smckusick for (;;) { /* keep looping until there is nothing left to 3418805Smckusick reduce */ 3428805Smckusick 3438805Smckusick switch (p_stack[tos]) { 3448805Smckusick 3458805Smckusick case stmt: 3468805Smckusick switch (p_stack[tos - 1]) { 3478805Smckusick 3488805Smckusick case stmt: 3498805Smckusick case stmtl: 3508805Smckusick /* stmtl stmt or stmt stmt */ 3518805Smckusick p_stack[--tos] = stmtl; 3528805Smckusick break; 3538805Smckusick 3548805Smckusick case dolit: 3558805Smckusick /* <do> <stmt> */ 3568805Smckusick p_stack[--tos] = dohead; 3578805Smckusick i_l_follow = il[tos]; 3588805Smckusick break; 3598805Smckusick 3608805Smckusick case ifstmt: 3618805Smckusick /* <if> <stmt> */ 3628805Smckusick p_stack[--tos] = ifhead; 3638805Smckusick for (i = tos - 1; 3648805Smckusick ( 3658805Smckusick p_stack[i] != stmt 3668805Smckusick && 3678805Smckusick p_stack[i] != stmtl 3688805Smckusick && 3698805Smckusick p_stack[i] != lbrace 3708805Smckusick ); 3718805Smckusick --i); 3728805Smckusick i_l_follow = il[i]; 3738805Smckusick /* for the time being, we will assume that there is no else 3748805Smckusick on this if, and set the indentation level accordingly. 3758805Smckusick If an else is scanned, it will be fixed up later */ 3768805Smckusick break; 3778805Smckusick 3788805Smckusick case swstmt: 3798805Smckusick /* <switch> <stmt> */ 3808805Smckusick case_ind = cstk[tos - 1]; 3818805Smckusick 3828805Smckusick case decl: /* finish of a declaration */ 3838805Smckusick case elsehead: 3848805Smckusick /* <<if> <stmt> else> <stmt> */ 3858805Smckusick case forstmt: 3868805Smckusick /* <for> <stmt> */ 3878805Smckusick case whilestmt: 3888805Smckusick /* <while> <stmt> */ 3898805Smckusick p_stack[--tos] = stmt; 3908805Smckusick i_l_follow = il[tos]; 3918805Smckusick break; 3928805Smckusick 3938805Smckusick default: /* <anything else> <stmt> */ 3948805Smckusick return; 3958805Smckusick 3968805Smckusick } /* end of section for <stmt> on top of stack */ 3978805Smckusick break; 3988805Smckusick 3998805Smckusick case whilestmt: /* while (...) on top */ 4008805Smckusick if (p_stack[tos - 1] == dohead) { 4018805Smckusick /* it is termination of a do while */ 4028805Smckusick p_stack[--tos] = stmt; 4038805Smckusick break; 4048805Smckusick } 4058805Smckusick else 4068805Smckusick return; 4078805Smckusick 4088805Smckusick default: /* anything else on top */ 4098805Smckusick return; 4108805Smckusick 4118805Smckusick } /* end of big switch */ 4128805Smckusick 4138805Smckusick } /* end of reduction phase for (;;) */ 4148805Smckusick } 415