home *** CD-ROM | disk | FTP | other *** search
- /* PG_PARSE.C
- Copyright (C) 1992 Keith L. Robertson All Rights Reserved
-
- Implementation of parser.
- Need to add table produced by the PGEN Parser Generator.
-
- Any user of 'parse()' must ensure that the following are defined:
-
- 1) The type 'LEX_INFO', that defines info relevant to token
- lexemes and parser nonterminal symbols.
-
- 2) Global variable 'lexeme' of type LEX_INFO in which the
- lexer returns information related to the token it last saw.
-
- 3) Global variable 'USHORT last_token', which is the token number
- returned by the last call to 'get_token()'.
-
- 4) Function 'USHORT get_token()', which reads the input stream and
- returns the token it saw, with related information in 'lexeme'.
-
- 5) Procedure 'VOID log_error (USHORT etype, CSTRING desc)', which
- prints an error message based on the given error type and
- description. See EXPR_LEX.H for a description.
-
- 6) Two operations on type 'LEX_INFO', probably through macros:
-
- VOID set_jumped(LEX_INFO& lex_info, INT value), or
- #define set_jumped(lex_info,value)
- // Mark 'lex_info' as jumped if 'value' is true,
- // and as not jumped if 'value' is false.
- // Used by the parser to mark/unmark stack objects.
- INT was_jumped(LEX_INFO& lex_info), or
- #define was_jumped(lex_info)
- // Return true if 'lex_info' is marked as jumped.
-
- The lexical analyzer must ensure that 'lexeme' is marked as not jumped.
- The 'LEX_INFO&' sytax above is actually valid C++, not C.
- It means that in the call, you specify the structure to pass without
- the '&' address-of operator, and the pointer is actually passed.
- Therefore, call using "was_jumped (attr [num])", for example,
- NOT "was_jumped (& attr [num])".
- */
- /* Lexer header must go first to define LEX_INFO. */
- #include "expr_lex.h" /* Get token definitions */
- /**** Replace with your lexical analyzer header file. ****/
- #include "pg_parse.h" /* Get type definitions for parse tables */
-
- /* If STACK_SIZE is set (nonzero), the stack will be checked */
- /* for overflow each time something is pushed onto it. */
- #define STACK_SIZE 0
-
-
- extern USHORT state_stack [];
- extern LEX_INFO state_value [];
-
- LEX_INFO* attr; /* Pass attribute info to semantic actions */
-
-
- /* ------------------------------------- */
-
- /* Return true if bit 'bitidx' is set in 'bitmap' */
- BOOL bitlookup (USHORT* bitmap, USHORT bitidx)
- { USHORT idx = bitidx >> 4;
- USHORT bmp = 1 << (bitidx & 0xF);
- return bitmap [idx] & bmp;
- }
-
- VOID bitset (USHORT* bitmap, USHORT bitidx, BOOL value)
- { USHORT idx = bitidx >> 4;
- USHORT bmp = 1 << (bitidx & 0xF);
- if (! value) { bitmap [idx] &= ~bmp; }
- else { bitmap [idx] |= bmp; }
- }
-
-
- /* ------------------------------------- */
-
- extern ACTION_ITEM action_list [];
- extern USHORT action_index [];
-
- static ACTION _near action (USHORT state, USHORT next)
- { USHORT idx = action_index [state];
- ACTION ANY_action = no_change (0);
- ACTION act;
- while (1) {
- USHORT tok = action_list [idx].token;
- if (tok == ANY_TK) {
- if (ANY_action != no_change (0)) { act = ANY_action; }
- else { act = action_list [idx].action; }
- break;
- }
- else if (tok == next) {
- act = action_list [idx].action;
- break;
- }
- else if (tok & BR) {
- if (ANY_action == no_change (0)) {
- ANY_action = action_list [idx].action;
- }
- idx = (tok ^ BR);
- }
- else { ++idx; }
- }
- return act;
- }
-
-
- /* ------------------------------------- */
-
- extern GOTO_LIST_ITEM goto_list [];
- extern USHORT goto_index [];
-
- static USHORT _near go_to (USHORT state, USHORT nonterm)
- { USHORT idx = goto_index [nonterm];
- while (1) {
- USHORT chkst = goto_list [idx].cur_state;
- if (chkst == ANY_ST || chkst == state) { break; }
- ++idx;
- }
- return goto_list [idx].nxt_state;
- }
-
-
- /* ------------------------------------- */
-
- extern PRODUCTION_INFO production [];
-
- SHORT top = 0; /* Index of top state on stack. Can go negative. */
-
- VOID parse ()
- {
- PRODUCTION_INFO* pr;
- USHORT next_tok = get_token ();
-
- state_stack [top] = 0; /* Start in state 0 */
-
- while (1) {
- ACTION act = action (state_stack [top], next_tok);
- USHORT sec = second_part (act);
-
- switch (action_part (act)) {
- /* ------------------------------------- */
- case JUMP_ACTION:
- if (act == error(0)) {
- /* Token seen was not expected. */
- do {
- act = action (state_stack [top], ERR_TK);
- if (action_part (act) == SHIFT_ACTION) { break; }
- --top;
- } while (top >= 0);
- if (top < 0) {
- log_error (FATAL, "no error processing available for syntax error.");
- }
- else if (next_tok == 0) {
- log_error (FATAL, "premature end of input.");
- }
-
- /* Push to an error state, but don't consume token. */
- state_stack [++top] = second_part (act);
- }
- else {
- /* An optional nonterminal is being jumped. */
- ++ top;
-
- #if STACK_SIZE
- if (STACK_SIZE <= top) { goto STACK_OVERFLOW; }
- #endif
-
- /* 'sec' is the state being jumped. */
- state_stack [top] = sec;
- /* Mark it as a jumped lexeme. */
- set_jumped (state_value [top], 1);
- }
- break;
-
- /* ------------------------------------- */
- case REDUCE_ACTION:
- pr = & production [sec];
-
- /* Reset 'top' to point to state beginning the production. */
- /* (An empty production will push a new state on the stack.) */
- top = top - pr->size_m1;
-
- #if STACK_SIZE
- if (STACK_SIZE <= top) { goto STACK_OVERFLOW; }
- #endif
-
- if (pr->sem_action) {
- /* Set up global for semantic action. */
- attr = & (state_value [top]);
- (* pr->sem_action) (); /* Do semantic action. */
- }
-
- /* Assign the go_to state after reduction */
- state_stack [top] = go_to (state_stack [top-1], pr->nonterm);
-
- if (was_jumped (state_value [top])) {
- /* This nonterm is not jumped, but it may have begun with */
- /* a jumped symbol. Ensure it is marked as not jumped. */
- set_jumped (state_value [top], 0);
- }
-
- /* Reassign in case sem action called get_token(). */
- next_tok = last_token;
- break;
-
- /* ------------------------------------- */
- case SHIFT_ACTION:
- ++ top;
-
- #if STACK_SIZE
- if (STACK_SIZE <= top) {
- STACK_OVERFLOW:
- log_error (FATAL, "input too complex. Parse stack overflow.");
- }
- #endif
-
- state_stack [top] = sec; /* Push state shifted to */
- state_value [top] = lexeme; /* Assign token value */
- /* The lexical analyzer must ensure that */
- /* its tokens are marked as not jumped. */
-
- next_tok = get_token (); /* Advance input stream */
- break;
-
- /* ------------------------------------- */
- case ACCEPT_ACTION:
- goto DONE; /* Break out of loop. */
-
- /* ------------------------------------- */
- }
- }
- DONE: ;
- }
-
-
- /* ------------------------------------- */
-
- VOID skip_to_token (USHORT tok)
- { while (last_token != tok && last_token != EOS) {
- get_token ();
- }
- }
-
- VOID skip_to_bittok (USHORT* tokmap)
- { /* Set EOS bit so we don't have to check it explicitly. */
- tokmap [0] |= 1;
- while ( ! bitlookup (tokmap, last_token) ) {
- get_token ();
- }
- }
-