home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 20 / AACD20.BIN / AACD / Programming / Jikes / Source / src / parser.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-24  |  23.8 KB  |  792 lines

  1. // $Id: parser.cpp,v 1.12 2001/01/10 16:49:45 mdejong Exp $
  2. //
  3. // This software is subject to the terms of the IBM Jikes Compiler
  4. // License Agreement available at the following URL:
  5. // http://www.ibm.com/research/jikes.
  6. // Copyright (C) 1996, 1998, International Business Machines Corporation
  7. // and others.  All Rights Reserved.
  8. // You must accept the terms of that agreement to use this software.
  9. //
  10. #include "parser.h"
  11. #include "ast.h"
  12.  
  13. #ifdef    HAVE_JIKES_NAMESPACE
  14. namespace Jikes {    // Open namespace Jikes block
  15. #endif
  16.  
  17. void Parser::ReallocateStacks()
  18. {
  19.     int old_stack_length = stack_length;
  20.  
  21.     stack_length += STACK_INCREMENT;
  22.  
  23.     assert(stack_length <= SHRT_MAX);
  24.  
  25.     int *old_stack = stack;
  26.     stack = (int *) memmove(new int[stack_length], stack, old_stack_length * sizeof(int));
  27.     delete [] old_stack;
  28.  
  29.     Location *old_location_stack = location_stack;
  30.     location_stack = (Location *) memmove(new Location[stack_length], location_stack, old_stack_length * sizeof(Location));
  31.     delete [] old_location_stack;
  32.  
  33.     Ast **old_parse_stack = parse_stack;
  34.     parse_stack = (Ast **) memmove(new Ast *[stack_length], parse_stack, old_stack_length * sizeof(Ast *));
  35.     delete [] old_parse_stack;
  36.     parse_stack[old_stack_length] = NULL; // the first time through, we initialize parse_stack[0] to NULL !!!
  37.  
  38.     int *old_temp_stack = temp_stack;
  39.     temp_stack = (int *) memmove(new int[stack_length], temp_stack, old_stack_length * sizeof(int));
  40.     delete [] old_temp_stack;
  41.  
  42.     return;
  43. }
  44.  
  45.  
  46. AstListNode *Parser::AllocateListNode()
  47. {
  48.     AstListNode *p;
  49.  
  50.     if (free_list_nodes)
  51.     {
  52.         p = free_list_nodes;
  53.         free_list_nodes = free_list_nodes -> next;
  54.     }
  55.     else p = list_node_pool -> NewListNode();
  56.  
  57.     return p;
  58. }
  59.  
  60.  
  61. void Parser::FreeCircularList(AstListNode *tail)
  62. {
  63.     AstListNode *root = tail -> next;
  64.     tail -> next = free_list_nodes;
  65.     free_list_nodes = root;
  66.  
  67.     return;
  68. }
  69.  
  70.  
  71. AstPackageDeclaration *Parser::PackageHeaderParse(LexStream *lex_stream_, StoragePool *ast_pool_)
  72. {
  73.     AstPackageDeclaration *package_declaration = NULL;
  74.  
  75.     lex_stream_ -> Reset();
  76.  
  77.     if (lex_stream_ -> Kind(lex_stream_ -> Peek()) == TK_package)
  78.     {
  79.         ast_pool = ast_pool_;
  80.  
  81.         parse_package_header_only = true;
  82.         end_token = LexStream::LEX_INFINITY; // We are parsing the whole input and not just a segment.
  83.         lex_stream = lex_stream_;
  84.         Ast *ast = HeaderParse();
  85.         parse_package_header_only = false;
  86.  
  87.         if (ast)
  88.         {
  89.             AstCompilationUnit *compilation_unit = ast -> CompilationUnitCast();
  90.             if (compilation_unit && (! compilation_unit -> BadCompilationUnitCast()))
  91.                 package_declaration = compilation_unit -> package_declaration_opt;
  92.         }
  93.     }
  94.  
  95.     return package_declaration;
  96. }
  97.  
  98.  
  99. AstCompilationUnit *Parser::HeaderParse(LexStream *lex_stream_, StoragePool *ast_pool_)
  100. {
  101.     lex_stream_ -> Reset();
  102.  
  103.     body_pool = new StoragePool(lex_stream_ -> NumTokens());
  104.     ast_pool = (ast_pool_ ? ast_pool_ : body_pool);
  105.     list_node_pool = new StoragePool(lex_stream_ -> NumTokens());
  106.     free_list_nodes = NULL;
  107.     AstCompilationUnit *compilation_unit = NULL;
  108.  
  109.     parse_header_only = true;
  110.     end_token = LexStream::LEX_INFINITY; // We are parsing the whole input and not just a segment.
  111.     lex_stream = lex_stream_;
  112.     Ast *ast = HeaderParse();
  113.     parse_header_only = false;
  114.  
  115.     if (ast)
  116.     {
  117.         compilation_unit = ast -> CompilationUnitCast();
  118.         if (compilation_unit && (! compilation_unit -> BadCompilationUnitCast()))
  119.         {
  120.             if (compilation_unit -> NumTypeDeclarations() == 0)
  121.                 compilation_unit -> kind = Ast::EMPTY_COMPILATION;
  122.         }
  123. // STG:
  124. //      else delete ast;
  125. //
  126.     }
  127.  
  128.     //
  129.     // If we succesfully parsed a compilation unit, allocate a storage pool for it.
  130.     // Subtract the amount of space that's already been allocated for the headers
  131.     // from the estimate for the bodies.
  132.     //
  133.     if (compilation_unit)
  134.          compilation_unit -> ast_pool = body_pool;
  135.     else delete body_pool;
  136.  
  137.     delete list_node_pool; // free the pool of list nodes
  138.  
  139.     return compilation_unit;
  140. }
  141.  
  142.  
  143. Ast *Parser::HeaderParse()
  144. {
  145.     TokenObject curtok = lex_stream -> Gettoken();
  146.     int act = START_STATE,
  147.               current_kind = lex_stream -> Kind(curtok);
  148.  
  149. /*****************************************************************/
  150. /* Start parsing.                                                */
  151. /*****************************************************************/
  152.     state_stack_top = -1;
  153.  
  154.     //
  155.     // Process a terminal
  156.     //
  157.     for (;;)
  158.     {
  159.         if (++state_stack_top >= stack_length)
  160.             ReallocateStacks();
  161.  
  162.         stack[state_stack_top] = act;
  163.         location_stack[state_stack_top] = Loc(curtok);
  164.  
  165.         act = t_action(act, current_kind, lex_stream);
  166.  
  167.         if (act <= NUM_RULES)
  168.             state_stack_top--; // make reduction look like a shift-reduce
  169.         else if (act > ERROR_ACTION)
  170.         {
  171. // STG:
  172. //            token_action(curtok);
  173.             curtok = lex_stream -> Gettoken();
  174.             current_kind = lex_stream -> Kind(curtok);
  175.  
  176.             act -= ERROR_ACTION;
  177.         }
  178.         else if (act < ACCEPT_ACTION)
  179.         {
  180. // STG:
  181. //            token_action(curtok);
  182.             curtok = lex_stream -> Gettoken();
  183.             current_kind = lex_stream -> Kind(curtok);
  184.  
  185.             continue;
  186.         }
  187.         else break;
  188.  
  189.         //
  190.         // Process a non_terminal
  191.         //
  192.         do
  193.         {
  194.             state_stack_top -= (rhs[act] - 1);
  195.             (this ->* rule_action[act])();
  196.             act = nt_action(stack[state_stack_top], lhs[act]);
  197.         } while(act <= NUM_RULES);
  198.     } /* process_terminal */
  199.  
  200.     if (act == ERROR_ACTION)
  201.     {
  202.         //
  203.         // If any error is found in a package declaration, do not try to repair it.
  204.         //
  205.         if (! parse_package_header_only)
  206.             RepairParse(curtok);
  207.  
  208.         if (parse_stack[0] && parse_stack[0] -> CompilationUnitCast())
  209.             parse_stack[0] -> kind = Ast::BAD_COMPILATION;
  210.         else
  211.         {
  212. // STG:
  213. //            delete parse_stack[0];
  214.             parse_stack[0] = NULL;
  215.         }
  216.     }
  217.  
  218.     return parse_stack[0];
  219. }
  220.  
  221.  
  222. bool Parser::BodyParse(LexStream *lex_stream_, AstClassBody *class_body)
  223. {
  224.     assert(class_body -> UnparsedClassBodyCast());
  225.  
  226.     lex_stream = lex_stream_;
  227.     ast_pool = class_body -> pool;
  228.     body_pool = class_body -> pool;
  229.     list_node_pool = new StoragePool(lex_stream_ -> NumTokens());
  230.     free_list_nodes = NULL;
  231.  
  232.     bool no_errors_detected = Body(class_body);
  233.  
  234.     delete list_node_pool; // free the pool of list nodes
  235.  
  236.     class_body -> mark_parsed();
  237.  
  238.     return no_errors_detected;
  239. }
  240.  
  241.  
  242. bool Parser::Body(AstClassBody *class_body)
  243. {
  244.     bool no_errors_detected = true;
  245.  
  246.     for (int i = 0; i < class_body -> NumConstructors(); i++)
  247.     {
  248.         AstConstructorDeclaration *constructor_decl = class_body -> Constructor(i);
  249.  
  250.         if (constructor_decl -> constructor_symbol)
  251.         {
  252.             AstConstructorBlock *block = constructor_decl -> constructor_body;
  253.             end_token = block -> right_brace_token; // last token in the body
  254.  
  255.             AstStatement *new_body = (AstStatement *) ParseSegment(block -> left_brace_token);
  256.  
  257.             if (! new_body)
  258.                 no_errors_detected = false;
  259.             else
  260.             {
  261.                 AstConstructorBlock *new_block = new_body -> ConstructorBlockCast();
  262.  
  263.                 if (! new_block)
  264.                 {
  265.                     new_block                                        = ast_pool -> GenConstructorBlock();
  266.                     new_block -> left_brace_token                    = new_body -> LeftToken();
  267.                     new_block -> explicit_constructor_invocation_opt = NULL;
  268.                     new_block -> block                               = (AstBlock *) new_body;
  269.                     new_block -> right_brace_token                   = new_body -> RightToken();
  270.                 }
  271. // STG:
  272. //                delete block; // destroy old empty block
  273. //
  274.                 constructor_decl -> constructor_body = new_block;
  275.             }
  276.         }
  277.     }
  278.  
  279.     for (int j = 0; j < class_body -> NumMethods(); j++)
  280.     {
  281.         AstMethodDeclaration *method_decl = class_body -> Method(j);
  282.  
  283.         if (method_decl -> method_symbol)
  284.         {
  285.             AstBlock *block = method_decl -> method_body -> BlockCast();
  286.  
  287.             if (block)
  288.             {
  289.                 end_token = block -> right_brace_token; // last token in the body
  290.                 AstStatement *new_block = (AstStatement *) ParseSegment(block -> left_brace_token);
  291.  
  292.                 if (! new_block) // a bad block ?
  293.                     no_errors_detected = false;
  294.                 else
  295.                 {
  296.                     //
  297.                     // The block associated with the method may syntactically be either a
  298.                     // block or a constructor block. If it is a block, nest it inside the
  299.                     // initial block. If it is a constructor block, replace the initial block
  300.                     // by the constructor block.
  301.                     //
  302.                     if (new_block -> BlockCast())
  303.                         block -> AddStatement(new_block);
  304.                     else
  305.                     {
  306.                         method_decl -> method_body = new_block;
  307. // STG:
  308. //                        delete block; // destroy old empty block
  309.                     }
  310.                 }
  311.             }
  312.         }
  313.     }
  314.  
  315.     for (int k = 0; k < class_body -> NumNestedClasses(); k++)
  316.         no_errors_detected = no_errors_detected && Body(class_body -> NestedClass(k) -> class_body);
  317.  
  318.     for (int l = 0; l < class_body -> NumNestedInterfaces(); l++)
  319.         no_errors_detected = no_errors_detected && Body(class_body -> NestedInterface(l));
  320.  
  321.     return no_errors_detected;
  322. }
  323.  
  324. bool Parser::BodyParse(LexStream *lex_stream_, AstInterfaceDeclaration *interface_declaration)
  325. {
  326.     assert(interface_declaration -> UnparsedInterfaceBodyCast());
  327.  
  328.     lex_stream = lex_stream_;
  329.     ast_pool = interface_declaration -> pool;
  330.     body_pool = interface_declaration -> pool;
  331.     list_node_pool = new StoragePool(lex_stream_ -> NumTokens());
  332.     free_list_nodes = NULL;
  333.  
  334.     bool no_errors_detected = Body(interface_declaration);
  335.  
  336.     delete list_node_pool; // free the pool of list nodes
  337.  
  338.     interface_declaration -> mark_parsed();
  339.  
  340.     return no_errors_detected;
  341. }
  342.  
  343.  
  344. bool Parser::Body(AstInterfaceDeclaration *interface_declaration)
  345. {
  346.     bool no_errors_detected = true;
  347.  
  348.     for (int k = 0; k < interface_declaration -> NumNestedClasses(); k++)
  349.         no_errors_detected = no_errors_detected && Body(interface_declaration -> NestedClass(k) -> class_body);
  350.  
  351.     for (int l = 0; l < interface_declaration -> NumNestedInterfaces(); l++)
  352.         no_errors_detected = no_errors_detected && Body(interface_declaration -> NestedInterface(l));
  353.  
  354.     return no_errors_detected;
  355. }
  356.  
  357.  
  358. bool Parser::InitializerParse(LexStream *lex_stream_, AstClassBody *class_body)
  359. {
  360.     lex_stream = lex_stream_;
  361.     ast_pool = class_body -> pool;
  362.     body_pool = class_body -> pool;
  363.     list_node_pool = new StoragePool(lex_stream_ -> NumTokens());
  364.     free_list_nodes = NULL;
  365.  
  366.     bool no_errors_detected = Initializer(class_body);
  367.  
  368.     delete list_node_pool; // free the pool of list nodes
  369.  
  370.     return no_errors_detected;
  371. }
  372.  
  373.  
  374. bool Parser::InitializerParse(LexStream *lex_stream_, AstInterfaceDeclaration *interface_declaration)
  375. {
  376.     lex_stream = lex_stream_;
  377.     ast_pool = interface_declaration -> pool;
  378.     body_pool = interface_declaration -> pool;
  379.     list_node_pool = new StoragePool(lex_stream_ -> NumTokens());
  380.     free_list_nodes = NULL;
  381.  
  382.     bool no_errors_detected = Initializer(interface_declaration);
  383.  
  384.     delete list_node_pool; // free the pool of list nodes
  385.  
  386.     return no_errors_detected;
  387. }
  388.  
  389.  
  390. bool Parser::Initializer(AstClassBody *class_body)
  391. {
  392.     bool no_errors_detected = true;
  393.  
  394.     for (int i = 0; i < class_body -> NumStaticInitializers(); i++)
  395.     {
  396.          AstBlock *block = class_body -> StaticInitializer(i) -> block;
  397.          end_token = block -> right_brace_token; // last token in the body
  398.          class_body -> StaticInitializer(i) -> block = (AstBlock *) ParseSegment(block -> left_brace_token);
  399.  
  400.         if (! class_body -> StaticInitializer(i) -> block)
  401.         {
  402.             no_errors_detected = false;
  403.             class_body -> StaticInitializer(i) -> block = block; // restore old empty block
  404.         }
  405. // STG:
  406. //      else
  407. //      {
  408. //          delete block; // destroy old empty block
  409. //      }
  410.     }
  411.  
  412.     for (int j = 0; j < class_body -> NumBlocks(); j++)
  413.     {
  414.          AstBlock *block = class_body -> Block(j);
  415.          end_token = block -> right_brace_token; // last token in the body
  416.          class_body -> Block(j) = (AstBlock *) ParseSegment(block -> left_brace_token);
  417.  
  418.         if (! class_body -> Block(j))
  419.         {
  420.             no_errors_detected = false;
  421.             class_body -> Block(j) = block; // restore old empty block
  422.         }
  423. //
  424. // STG: if we ever go back to a new/free model of allocating Ast nodes
  425. // This loop needs to be rewritten as otherwise, the new block allocated
  426. // here would cause a memory leak since the class_body_declarations list
  427. // is unaware of it. The solution is to iterate over the class_body_declarations
  428. // list in order to locate the old block, free it and update the class_body_declarations
  429. // list to point to the new block.
  430. //
  431.     }
  432.  
  433.     for (int k = 0; k < class_body -> NumNestedClasses(); k++)
  434.         no_errors_detected = no_errors_detected && Initializer(class_body -> NestedClass(k) -> class_body);
  435.  
  436.     for (int l = 0; l < class_body -> NumNestedInterfaces(); l++)
  437.         no_errors_detected = no_errors_detected && Initializer(class_body -> NestedInterface(l));
  438.  
  439.     return no_errors_detected;
  440. }
  441.  
  442.  
  443. bool Parser::Initializer(AstInterfaceDeclaration *interface_declaration)
  444. {
  445.     bool no_errors_detected = true;
  446.  
  447.     for (int k = 0; k < interface_declaration -> NumNestedClasses(); k++)
  448.         no_errors_detected = no_errors_detected && Initializer(interface_declaration -> NestedClass(k) -> class_body);
  449.  
  450.     for (int l = 0; l < interface_declaration -> NumNestedInterfaces(); l++)
  451.         no_errors_detected = no_errors_detected && Initializer(interface_declaration -> NestedInterface(l));
  452.  
  453.     return no_errors_detected;
  454. }
  455.  
  456.  
  457. Ast *Parser::ParseSegment(TokenObject start_token)
  458. {
  459.     //
  460.     // The next call to Gettoken will return the start_token.
  461.     // However, we initialize curtok to start_token in order
  462.     // to obtain a valid location for the BodyMarker.
  463.     //
  464.     lex_stream -> Reset(start_token);
  465.     TokenObject curtok = start_token; // get the location of the start_token
  466.     int act = START_STATE,
  467.               current_kind = TK_BodyMarker;
  468.  
  469. /*****************************************************************/
  470. /* Start parsing.                                                */
  471. /*****************************************************************/
  472.     state_stack_top = -1;
  473.  
  474.     //
  475.     // Process a terminal
  476.     //
  477.     for (;;)
  478.     {
  479.         if (++state_stack_top >= stack_length)
  480.             ReallocateStacks();
  481.  
  482.         stack[state_stack_top] = act;
  483.         location_stack[state_stack_top] = Loc(curtok);
  484.  
  485.         act = t_action(act, current_kind, lex_stream);
  486.  
  487.         if (act <= NUM_RULES)
  488.             state_stack_top--; // make reduction look like a shift-reduce
  489.         else if (act > ERROR_ACTION)
  490.         {
  491. // STG:
  492. //            token_action(curtok);
  493.             curtok = lex_stream -> Gettoken(end_token);
  494.             current_kind = lex_stream -> Kind(curtok);
  495.  
  496.             act -= ERROR_ACTION;
  497.         }
  498.         else if (act < ACCEPT_ACTION)
  499.         {
  500. // STG:
  501. //            token_action(curtok);
  502.             curtok = lex_stream -> Gettoken(end_token);
  503.             current_kind = lex_stream -> Kind(curtok);
  504.  
  505.             continue;
  506.         }
  507.         else break;
  508.  
  509.         //
  510.         // Process a nonterminal
  511.         //
  512.         do
  513.         {
  514.             state_stack_top -= (rhs[act] - 1);
  515.             (this ->* rule_action[act])();
  516.             act = nt_action(stack[state_stack_top], lhs[act]);
  517.         } while(act <= NUM_RULES);
  518.     } /* process_terminal */
  519.  
  520.     if (act == ERROR_ACTION)
  521.     {
  522.         RepairParse(curtok);
  523.  
  524. // STG:
  525. //        delete parse_stack[0];
  526.         parse_stack[0] = NULL;
  527.     }
  528.  
  529.     return parse_stack[0];
  530. }
  531.  
  532.  
  533. void Parser::RepairParse(TokenObject curtok)
  534. {
  535.     //
  536.     // Repair an error
  537.     //
  538.     for (;;)
  539.     {
  540.         //
  541.         // Pop state stack up to first state that had an
  542.         // action on the error token.  The net effect is to
  543.         // remove all default reductions on an empty rule
  544.         // caused by the error token.
  545.         //
  546.         int k;
  547.         for (k = state_stack_top - 1; k >= 0 && location_stack[k] == Loc(curtok); k--)
  548.              ;
  549.         k++;
  550. // STG:
  551. //        for (int i = k; i < state_stack_top; i++)
  552. //        {
  553. //            delete parse_stack[i];
  554. //        }
  555.  
  556.         state_stack_top = k;
  557.  
  558.         ErrorRepair(curtok);
  559.  
  560.         curtok = lex_stream -> Gettoken(end_token);
  561.         int act = stack[state_stack_top--];
  562.         int current_kind = lex_stream -> Kind(curtok);
  563.  
  564.         //
  565.         // Process a terminal
  566.         //
  567.         for (;;)
  568.         {
  569.             if (++state_stack_top >= stack_length)
  570.                  ReallocateStacks();
  571.  
  572.             stack[state_stack_top] = act;
  573.             location_stack[state_stack_top] = Loc(curtok);
  574.  
  575.             act = t_action(act, current_kind, lex_stream);
  576.  
  577.             if (act <= NUM_RULES)
  578.                 state_stack_top--; // make reduction look like a shift-reduce
  579.             else if (act > ERROR_ACTION)
  580.             {
  581. // STG:
  582. //                token_action(curtok);
  583.                 curtok = lex_stream -> Gettoken(end_token);
  584.                 current_kind = lex_stream -> Kind(curtok);
  585.  
  586.                 act -= ERROR_ACTION;
  587.             }
  588.             else if (act < ACCEPT_ACTION)
  589.             {
  590. // STG:
  591. //                token_action(curtok);
  592.                 curtok = lex_stream -> Gettoken(end_token);
  593.                 current_kind = lex_stream -> Kind(curtok);
  594.  
  595.                 continue;
  596.             }
  597.             //
  598.             // Since the null string is a valid Java program, this function
  599.             // will always succeed even if it has to delete the whole input.
  600.             //
  601.             else if (act == ACCEPT_ACTION)
  602.                  return;
  603.             else break; // loop around and keep trying until something is accepted.
  604.  
  605.             //
  606.             // Process a nonterminal
  607.             //
  608.             do
  609.             {
  610.                 state_stack_top -= (rhs[act] - 1);
  611.                 (this ->* rule_action[act])();
  612.                 act = nt_action(stack[state_stack_top], lhs[act]);
  613.             } while(act <= NUM_RULES);
  614.         } /* process_terminal */
  615.     }
  616.  
  617.     return;
  618. }
  619.  
  620.  
  621. //
  622. // This routine is invoked when an error is encountered in a "repair"
  623. // parser. It will place the parser back into a working configuration
  624. // by adjusting the state stack, the current token and the buffer.
  625. //
  626. void Parser::ErrorRepair(TokenObject error_token)
  627. {
  628.     SecondaryRepairInfo repair;
  629.  
  630.     repair.code = ERROR_CODE;
  631.     do
  632.     {
  633.         repair.distance = 0;
  634.         repair.num_deletions = state_stack_top + BUFF_UBOUND;
  635.  
  636.         buffer[1] = error_token;
  637.         buffer[0] = lex_stream -> Previous(buffer[1]);
  638.  
  639.         for (int k = 2; k < BUFF_SIZE; k++)
  640.             buffer[k] = lex_stream -> Next(buffer[k - 1]);
  641.  
  642.         int last_index;
  643.         for (last_index = MAX_DISTANCE - 1;
  644.              last_index >= 1 && lex_stream -> Kind(buffer[last_index]) == EOFT_SYMBOL;
  645.              last_index--);
  646.         last_index++;
  647.  
  648.         repair = ErrorSurgery(stack, state_stack_top, last_index, repair);
  649.         error_token = buffer[MAX_DISTANCE - MIN_DISTANCE + 2];
  650.     } while (repair.code == 0);
  651.  
  652. // STG:
  653. //    for (int i = repair.stack_position; i < state_stack_top; i++)
  654. //    {
  655. //        delete parse_stack[i];
  656. //    }
  657.  
  658.     state_stack_top = repair.stack_position;
  659.     lex_stream -> Reset(buffer[repair.buffer_position]);
  660.  
  661.     return;
  662. }
  663.  
  664.  
  665. //
  666. // Keep cutting "stuff" out around the error until a stable configuration
  667. // is found.
  668. //
  669. SecondaryRepairInfo Parser::ErrorSurgery
  670.          (int stck[], int stack_top,
  671.           int last_index, SecondaryRepairInfo repair)
  672. {
  673.     int stack_deletions = 0;
  674.     Location  previous_loc = Loc(buffer[2]);
  675.  
  676.     for (int top = stack_top; top >= 0 && repair.num_deletions >= stack_deletions; top--)
  677.     {
  678.         if (location_stack[top] < previous_loc)
  679.             stack_deletions++;
  680.         previous_loc = location_stack[top];
  681.  
  682.         for (int i = 1; i <= last_index && repair.num_deletions >= (stack_deletions + i - 1); i++)
  683.         {
  684.             int j = ParseCheck(stck, top, lex_stream -> Kind(buffer[i]), i + 1);
  685.  
  686.             if ((j - i + 1) > MIN_DISTANCE)
  687.             {
  688.                 int k = stack_deletions + i - 1;
  689.                 if ((k < repair.num_deletions) ||
  690.                     (j - k) > (repair.distance - repair.num_deletions))
  691.                 {
  692.                     repair.code = DELETION_CODE;
  693.                     repair.distance = j;
  694.                     repair.stack_position = top;
  695.                     repair.buffer_position = i;
  696.                     repair.num_deletions = k;
  697.                 }
  698.             }
  699.         }
  700.     }
  701.  
  702.     return repair;
  703. }
  704.  
  705.  
  706. /*****************************************************************/
  707. /* Try to parse until first_token and all tokens in BUFFER have  */
  708. /* been consumed, or an error is encountered. Return the number  */
  709. /* of tokens that were expended before the parse blocked.        */
  710. /*****************************************************************/
  711. int Parser::ParseCheck(int stck[], int stack_top, int first_token, int buffer_position)
  712. {
  713.     int max_pos,
  714.         indx,
  715.         ct,
  716.         act,
  717.         lhs_symbol;
  718.  
  719. /*****************************************************************/
  720. /* Initialize pointer for temp_stack and initialize maximum      */
  721. /* position of state stack that is still useful.                 */
  722. /*****************************************************************/
  723.     act = stck[stack_top];
  724.     if (first_token > NT_OFFSET)
  725.     {
  726.         temp_stack_top = stack_top;
  727.         max_pos = stack_top;
  728.         indx = buffer_position;
  729.         ct = lex_stream -> Kind(buffer[indx]);
  730.         lex_stream -> Reset(lex_stream -> Next(buffer[indx]));
  731.         lhs_symbol = first_token - NT_OFFSET;
  732.         act = nt_action(act, lhs_symbol);
  733.         if (act <= NUM_RULES)
  734.             goto process_non_terminal;
  735.     }
  736.     else
  737.     {
  738.         temp_stack_top = stack_top - 1;
  739.         max_pos = temp_stack_top;
  740.         indx = buffer_position - 1;
  741.         ct = first_token;
  742.         lex_stream -> Reset(buffer[buffer_position]);
  743.     }
  744.  
  745.     process_terminal: for (;;)
  746.     {
  747.         if (++temp_stack_top >= stack_length)  /* Stack overflow!!! */
  748.             return indx;
  749.         temp_stack[temp_stack_top] = act;
  750.  
  751.         act = t_action(act, ct, lex_stream);
  752.  
  753.         if (act <= NUM_RULES)                   /* reduce action */
  754.             temp_stack_top--;
  755.         else if (act < ACCEPT_ACTION ||          /* shift action */
  756.                  act > ERROR_ACTION)        /*shift-reduce action*/
  757.         {
  758.             if (indx == MAX_DISTANCE)
  759.                 return indx;
  760.             indx++;
  761.             ct = lex_stream -> Kind(buffer[indx]);
  762.             lex_stream -> Reset(lex_stream -> Next(buffer[indx]));
  763.             if (act > ERROR_ACTION)
  764.                  act -= ERROR_ACTION;
  765.             else goto process_terminal;
  766.         }
  767.         else if (act == ACCEPT_ACTION)           /* accept action */
  768.              return MAX_DISTANCE;
  769.         else return indx;                         /* error action */
  770.  
  771.         process_non_terminal:
  772.         do
  773.         {
  774.             temp_stack_top -= (rhs[act]-1);
  775.             lhs_symbol = lhs[act];
  776.             act = (temp_stack_top > max_pos
  777.                                   ? temp_stack[temp_stack_top]
  778.                                   : stck[temp_stack_top]);
  779.             act = nt_action(act, lhs_symbol);
  780.         } while(act <= NUM_RULES);
  781.  
  782.         max_pos = Min(max_pos, temp_stack_top);
  783.     } // process_terminal;
  784.  
  785.     return 0;
  786. }
  787.  
  788. #ifdef    HAVE_JIKES_NAMESPACE
  789. }            // Close namespace Jikes block
  790. #endif
  791.  
  792.