Logo Search packages:      
Sourcecode: cccc version File versions

pred.c

/*
 * pred.c -- source for predicate detection, manipulation
 *
 * SOFTWARE RIGHTS
 *
 * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
 * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
 * company may do whatever they wish with source code distributed with
 * PCCTS or the code generated by PCCTS, including the incorporation of
 * PCCTS, or its output, into commerical software.
 *
 * We encourage users to develop software with PCCTS.  However, we do ask
 * that credit is given to us for developing PCCTS.  By "credit",
 * we mean that if you incorporate our source code into one of your
 * programs (commercial product, research project, or otherwise) that you
 * acknowledge this fact somewhere in the documentation, research report,
 * etc...  If you like PCCTS and have developed a nice tool with the
 * output, please mention that you developed it using PCCTS.  In
 * addition, we ask that this header remain intact in our source code.
 * As long as these guidelines are kept, we expect to continue enhancing
 * this system and expect to make other tools available as they are
 * completed.
 *
 * ANTLR 1.33
 * Terence Parr
 * Parr Research Corporation
 * with Purdue University and AHPCRC, University of Minnesota
 * 1989-1998
 */

#include <stdio.h>
#include "pcctscfg.h"
#include "set.h"
#include "syn.h"
#include "hash.h"
#include "generic.h"
#include "dlgdef.h"
#include <ctype.h>

#ifdef __USE_PROTOS
static void complete_context_sets(RuleRefNode *, Predicate *);
static void complete_context_trees(RuleRefNode *, Predicate *);
#else
static void complete_context_sets();
static void complete_context_trees();
#endif

char *PRED_AND_LIST = "AND";
char *PRED_OR_LIST = "OR";

/*
 * In C mode, return the largest constant integer found as the
 * sole argument to LATEXT(i).
 *
 * In C++ mode, return the largest constant integer found as the
 * sole argument to LT(i) given that the char before is nonalpha.
 */

int
#ifdef __USE_PROTOS
predicateLookaheadDepth(ActionNode *a)
#else
predicateLookaheadDepth(a)
ActionNode *a;
#endif
{
      int     max_k=0;

    if (a->predEntry != NULL) {
       MR_pred_depth(a->predEntry->pred,&max_k);
       goto PREDENTRY_EXIT;
    }

      if ( GenCC )
      {
            /* scan for LT(i) */
            int k = 0;
            char *p = a->action;
            while ( p!=NULL )
            {
                  p = strstr(p, "LT(");
                  if ( p!=NULL )
                  {
                        if ( p>=a->action && !isalpha(*(p-1)) )
                        {
                              k = atoi(p+strlen("LT("));
                              if ( k>max_k ) max_k=k;
                        }
                        p += strlen("LT(");
                  }
            }
      }
      else {
            /* scan for LATEXT(i) */
            int k = 0;
            char *p = a->action;
            while ( p!=NULL )
            {
                  p = strstr(p, "LATEXT(");
                  if ( p!=NULL )
                  {
                        p += strlen("LATEXT(");
                        k = atoi(p);
                        if ( k>max_k ) max_k=k;
                  }
            }
      }

      if ( max_k==0 )
      {
            if ( !a->frmwarned )
            {
                  a->frmwarned = 1;
                  warnFL(eMsg1("predicate: %s missing, bad, or with i=0; assuming i=1",
                                     GenCC?"LT(i)":"LATEXT(i)"),
                           FileStr[a->file], a->line);
            }
            max_k = 1;
      }

/* MR10 */    if ( max_k > CLL_k) {
/* MR10 */        if ( !a->frmwarned )
/* MR10 */        {
/* MR10 */              a->frmwarned = 1;
/* MR11 */ errFL(eMsgd2("predicate refers to lookahead token %d. Semantic lookahead is limited to max(k,ck)==%d",
/* MR10 */                        max_k,CLL_k),
/* MR10 */                        FileStr[a->file],a->line);
/* MR10 */          if (max_k >= OutputLL_k) {
/* MR10 */            if (!GenCC) {
/* MR10 */              errFL(eMsgd("    the lookahead buffer size in C mode is %d token(s) (including the one just recognized)",
/* MR10 */                        OutputLL_k),
/* MR10 */                        FileStr[a->file],a->line);
/* MR10 */            };
/* MR10 */          };
/* MR10 */        };
/* MR10 */        max_k= CLL_k;
/* MR10 */    };

PREDENTRY_EXIT:
      return max_k;
}

/* Find all predicates in a block of alternatives.  DO NOT find predicates
 * behind the block because that predicate could depend on things set in
 * one of the nonoptional blocks
 */

Predicate *
#ifdef __USE_PROTOS
find_in_aSubBlk( Junction *alt )
#else
find_in_aSubBlk( alt )
Junction *alt;
#endif
{
      Predicate *a, *head=NULL, *tail=NULL, *root=NULL;
      Junction *p = alt;

    if (MRhoisting) {
      return MR_find_in_aSubBlk(alt);
    };
      for (; p!=NULL; p=(Junction *)p->p2)
      {
            /* ignore empty alts */
            if ( p->p1->ntype != nJunction ||
                   ((Junction *)p->p1)->jtype != EndBlk )
            {
                  a = find_predicates(p->p1);   /* get preds for this alt */
                  if ( a==NULL ) continue;

                  /* make an OR list of predicates */
                  if ( head==NULL )
                  {
                        root = new_pred();
                        root->expr = PRED_OR_LIST;
                        head = tail = a;
                        root->down = head;
                  }
                  else {
                        tail->right = a;
                        a->left = tail;
                        a->up = tail->up;
                        tail = a;
                  }
            }
      }

      /* if just one pred, remove OR root */
      if ( root!=NULL && root->down->right == NULL )
      {
            Predicate *d = root->down;
            free( (char *) root);
            return d;
      }

      return root;
}

Predicate *
#ifdef __USE_PROTOS
find_in_aOptBlk( Junction *alt )
#else
find_in_aOptBlk( alt )
Junction *alt;
#endif
{
      return find_in_aSubBlk( alt );
}

Predicate *
#ifdef __USE_PROTOS
find_in_aLoopBegin( Junction *alt )
#else
find_in_aLoopBegin( alt )
Junction *alt;
#endif
{
      return find_in_aSubBlk( (Junction *) alt->p1 ); /* get preds in alts */
}

Predicate *
#ifdef __USE_PROTOS
find_in_aPlusBlk( Junction *alt )
#else
find_in_aPlusBlk( alt )
Junction *alt;
#endif
{
      require(alt!=NULL&&alt->p2!=NULL, "invalid aPlusBlk");
      return find_in_aSubBlk( alt );
}

/* Look for a predicate;
 *
 * Do not pass anything but Junction nodes; no Actions, Tokens, RuleRefs.
 * This means that a "hoisting distance" of zero is the only distance
 * allowable.  Init actions are ignored.
 *
 * WARNING:
 *          Assumes no (..)? block after predicate for the moment.
 *          Does not check to see if pred is in production that can generate
 *                a sequence contained in the set of ambiguous tuples.
 *
 * Return the predicate found if any.
 */


Predicate *
#ifdef __USE_PROTOS
find_predicates( Node *alt )
#else
find_predicates( alt )
Node *alt;
#endif
{
#ifdef DBG_PRED
      Junction *j;
      RuleRefNode *r;
      TokNode *t;
#endif
      Predicate *pred;

      if ( alt==NULL ) return NULL;

#ifdef DBG_PRED
      switch ( alt->ntype )
      {
            case nJunction :
                  j = (Junction *) alt;
                  fprintf(stderr, "Junction(in %s)", j->rname);
                  switch ( j->jtype )
                  {
                        case aSubBlk :
                              fprintf(stderr,"aSubBlk\n");
                              break;
                        case aOptBlk :
                              fprintf(stderr,"aOptBlk\n");
                              break;
                        case aLoopBegin :
                              fprintf(stderr,"aLoopBeginBlk\n");
                              break;
                        case aLoopBlk :
                              fprintf(stderr,"aLoopBlk\n");
                              break;
                        case aPlusBlk :
                              fprintf(stderr,"aPlusBlk\n");
                              break;
                        case EndBlk :
                              fprintf(stderr,"EndBlk\n");
                              break;
                        case RuleBlk :
                              fprintf(stderr,"RuleBlk\n");
                              break;
                        case Generic :
                              fprintf(stderr,"Generic\n");
                              break;
                        case EndRule :
                              fprintf(stderr,"EndRule\n");
                              break;
                  }
                  break;
            case nRuleRef :
                  r = (RuleRefNode *) alt;
                  fprintf(stderr, "RuleRef(in %s)\n", r->rname);
                  break;
            case nToken :
                  t = (TokNode *) alt;
                  fprintf(stderr, "TokenNode(in %s)%s\n", t->rname, TokenString(t->token));
                  break;
            case nAction :
                  fprintf(stderr, "Action\n");
                  break;
      }
#endif

      switch ( alt->ntype )
      {
            case nJunction :
            {
                  Predicate *a, *b;
                  Junction *p = (Junction *) alt;     

                  /* lock nodes */
                  if ( p->jtype==aLoopBlk || p->jtype==RuleBlk ||
                         p->jtype==aPlusBlk || p->jtype==EndRule )
                  {
                        require(p->pred_lock!=NULL, "rJunc: lock array is NULL");
                        if ( p->pred_lock[1] )
                        {
                              return NULL;
                        }
                        p->pred_lock[1] = TRUE;
                  }

                  switch ( p->jtype )
                  {
                        case aSubBlk :
                              a = find_in_aSubBlk(p);
                              return a;   /* nothing is visible past this guy */
                        case aOptBlk :
                              a = find_in_aOptBlk(p);
                              return a;
                        case aLoopBegin :
                              a = find_in_aLoopBegin(p);
                              return a;
                        case aLoopBlk :
                              a = find_in_aSubBlk(p);
                              p->pred_lock[1] = FALSE;
                              return a;
                        case aPlusBlk :
                              a = find_in_aPlusBlk(p);
                              p->pred_lock[1] = FALSE;
                              return a;   /* nothing is visible past this guy */
                        case RuleBlk :
                              a = find_predicates(p->p1);
                              p->pred_lock[1] = FALSE;
                              return a;
                        case Generic :
                              a = find_predicates(p->p1);
                              b = find_predicates(p->p2);
                              if ( p->pred_lock!=NULL ) p->pred_lock[1] = FALSE;
                              if ( a==NULL ) return b;
                              if ( b==NULL ) return a;
                              /* otherwise OR the two preds together */
                              {
                              fatal_internal("hit unknown situation during predicate hoisting");
                              }
                        case EndBlk :
                        case EndRule :    /* Find no predicates after a rule ref */
                              return NULL;
                        default:
                              fatal_internal("this cannot be printed\n");
                              break;
                  }
            }
            case nAction :
            {
                  ActionNode *p = (ActionNode *) alt;
            if ( p->noHoist) return NULL;                           /* MR12c */
                  if ( p->init_action ) return find_predicates(p->next);
                  if ( p->is_predicate )
                  {
                        Tree *t=NULL;
#ifdef DBG_PRED
                        fprintf(stderr, "predicate: <<%s>>?\n", p->action);
#endif
                        if ( p->guardpred!=NULL )
                        {
                              pred = predicate_dup(p->guardpred);
                    MR_guardPred_plainSet(p,pred);                  /* MR12c */
                        }
                        else
                        {
                              pred = new_pred();
                              pred->k = predicateLookaheadDepth(p);
                              pred->source = p;
                              pred->expr = p->action;
                              if ( HoistPredicateContext && pred->k > 1 )
                              {
                                    if ( first_item_is_guess_block((Junction *)p->next) )
                                    {
                            warnFL("cannot compute context of predicate in front of (..)? block",
                            FileStr[p->file], p->line);
                                    }
                                    else
                                    {
                                          ConstrainSearch = 0;
/* MR11 */                  if (p->ampersandPred != NULL) {
/* MR11 */                                TRAV(p,
/* MR11 */                                       pred->k,
/* MR11 */                                       &(pred->completionTree), t);
/* MR11 */                  } else {
                                          TRAV(p->next,
                                                 pred->k,
                                                 &(pred->completionTree), t);
                            };
                                          pred->tcontext = t;
                            MR_check_pred_too_long(pred,pred->completionTree);
#ifdef DBG_PRED
                                          fprintf(stderr, "LL(%d) context:", pred->k);
                                          preorder(t);
                                          fprintf(stderr, "\n");
#endif
                                    }
                              }
                              else if ( HoistPredicateContext && pred->k == 1 )
                              {
                                    pred->scontext[1] = empty;
                                    if ( first_item_is_guess_block((Junction *)p->next) )
                                    {
                        warnFL("cannot compute context of predicate in front of (..)? block",
                                             FileStr[p->file], p->line);
                                    }
                                    else
                                    {
                                          REACH((Junction *)p->next,
                                                  1,
                                                  &(pred->completionSet),
                                                  pred->scontext[1]);
                            MR_check_pred_too_long(pred,pred->completionSet);
#ifdef DBG_PRED
                                          fprintf(stderr, "LL(1) context:");
                                          s_fprT(stderr, pred->scontext[1]);
                                          fprintf(stderr, "\n");
#endif
                                    }
                              }
                        }
                        {
                              Predicate  *d = find_predicates(p->next);
                    Predicate  *root;

/* Warning: Doesn't seem like the up pointers will all be set correctly;
 * TJP: that's ok, we're not using them now.
 */
                              if ( d!=NULL )
                              {
                                    root = new_pred();
                                    root->expr = PRED_AND_LIST;
                                    root->down = pred;
                                    pred->right = d;
                                    pred->up = root;
                                    d->left = pred;
                                    d->up = pred->up;
                                    return root;
                              }
                        }
                        return pred;
                  }
                  return NULL;
            }
            case nRuleRef :
            {
                  Predicate   *a;
                  RuleRefNode *p = (RuleRefNode *) alt;
                  Junction    *r;
            Junction    *save_MR_RuleBlkWithHalt;

                  RuleEntry *q = (RuleEntry *) hash_get(Rname, p->text);
                  if ( q == NULL )
                  {
                        warnFL( eMsg1("rule %s not defined",p->text), FileStr[p->file], p->line );
                        return NULL;
                  }
                  r = RulePtr[q->rulenum];
                  if ( r->pred_lock[1] )
                  {
                        /* infinite left-recursion; ignore 'cause LL sup 1 (k) analysis
                         * must have seen it earlier.
                         */
                        return NULL;
                  }

            /* MR10 There should only be one halt set at a time.        */
            /* MR10 Life would have been easier with a global variable  */
            /* MR10    (at least for this particular need)              */
            /* MR10 Unset the old one and set the new one, later undo.  */

            require(r->end->halt == FALSE,"should only have one halt at a time");

/* MR10 */  require(MR_RuleBlkWithHalt == NULL ||
/* MR10 */          (MR_RuleBlkWithHalt->jtype == RuleBlk && MR_RuleBlkWithHalt->end->halt == TRUE),
/* MR10 */             "RuleBlkWithHalt->end not RuleBlk or does not have halt set");
/* MR10 */  if (MR_RuleBlkWithHalt != NULL) {
/* MR10 */    MR_RuleBlkWithHalt->end->halt=FALSE;
/* MR10 */  };

/***        fprintf(stderr,"\nSetting halt on junction #%d\n",r->end->seq);     ***/

            require(r->end->halt == FALSE,"rule->end->halt already set");

            save_MR_RuleBlkWithHalt=MR_RuleBlkWithHalt;

/* MR10 */  MR_pointerStackPush(&MR_RuleBlkWithHaltStack,MR_RuleBlkWithHalt);
/* MR10 */  MR_pointerStackPush(&MR_PredRuleRefStack,p);

                  r->end->halt = TRUE;
/* MR10 */  MR_RuleBlkWithHalt=r;

                  a = find_predicates((Node *)r);

            require(r->end->halt == TRUE,"rule->end->halt not set");
            r->end->halt = FALSE;

/* MR10 */  MR_pointerStackPop(&MR_PredRuleRefStack);
/* MR10 */  MR_RuleBlkWithHalt=(Junction *) MR_pointerStackPop(&MR_RuleBlkWithHaltStack);

            require (MR_RuleBlkWithHalt==save_MR_RuleBlkWithHalt,
                    "RuleBlkWithHaltStack not consistent");

/* MR10 */  require(MR_RuleBlkWithHalt == NULL ||
/* MR10 */          (MR_RuleBlkWithHalt->jtype == RuleBlk && MR_RuleBlkWithHalt->end->halt == FALSE),
/* MR10 */             "RuleBlkWithHalt->end not RuleBlk or has no halt set");
/* MR10 */  if (MR_RuleBlkWithHalt != NULL) {
/* MR10 */    MR_RuleBlkWithHalt->end->halt=TRUE;
/* MR10 */  };

/***        fprintf(stderr,"\nRestoring halt on junction #%d\n",r->end->seq);   ***/

                  if ( a==NULL ) return NULL;

                  /* attempt to compute the "local" FOLLOW just like in normal lookahead
                   * computation if needed
                   */

                  complete_context_sets(p,a);
                  complete_context_trees(p,a);

/* MR10 */  MR_cleanup_pred_trees(a);

                  return a;
            }
            case nToken :
                  break;
      }

      return NULL;
}

#ifdef __USE_PROTOS
Predicate *MR_find_predicates_and_supp(Node *alt)
#else
Predicate *MR_find_predicates_and_supp(alt)
  Node      *alt;
#endif
{
    Predicate   *p;

    p=find_predicates(alt);
    p=MR_suppressK(alt,p);
    return p;
}

Predicate *
#ifdef __USE_PROTOS
new_pred( void )
#else
new_pred( )
#endif
{
      Predicate *p = (Predicate *) calloc(1,sizeof(Predicate)); /* MR10 */
      require(p!=NULL, "new_pred: cannot alloc predicate");
    p->scontext[0]=empty;
    p->scontext[1]=empty;
    p->completionTree=empty;
    p->completionSet=empty;
    p->plainSet=empty;
      return p;
}

static void
#ifdef __USE_PROTOS
complete_context_sets( RuleRefNode *p, Predicate *a )
#else
complete_context_sets( p, a )
RuleRefNode *p;
Predicate *a;
#endif
{
      set rk2, b;
      int k2;

#ifdef DBG_PRED
      fprintf(stderr, "enter complete_context_sets\n");
#endif
      for (; a!=NULL; a=a->right)
      {
            if ( a->expr == PRED_AND_LIST || a->expr == PRED_OR_LIST )
            {
                  complete_context_sets(p,a->down);
                  continue;
            }
            rk2 = b = empty;
            while ( !set_nil(a->completionSet) )
            {
                  k2 = set_int(a->completionSet);
                  set_rm(k2, a->completionSet);

            REACH(p->next, k2, &rk2, b);
                  set_orin(&(a->scontext[1]), b);
                  set_free(b);
            }

            set_orin(&(a->completionSet), rk2);/* remember what we couldn't do */
            set_free(rk2);
#ifdef DBG_PRED
            fprintf(stderr, "LL(1) context for %s(addr 0x%x) after ruleref:", a->expr, a);
            s_fprT(stderr, a->scontext[1]);
            fprintf(stderr, "\n");
#endif
/*          complete_context_sets(p, a->down);*/
      }
#ifdef DBG_PRED
      fprintf(stderr, "exit complete_context_sets\n");
#endif
}

static void
#ifdef __USE_PROTOS
complete_context_trees( RuleRefNode *p, Predicate *a )
#else
complete_context_trees( p, a )
RuleRefNode *p;
Predicate *a;
#endif
{
      set rk2;
      int k2;
      Tree *u;

#ifdef DBG_PRED
      fprintf(stderr, "enter complete_context_trees\n");
#endif
      for (; a!=NULL; a=a->right)
      {
            if ( a->expr == PRED_AND_LIST || a->expr == PRED_OR_LIST )
            {
                  complete_context_trees(p, a->down);
                  continue;
            }
            rk2 = empty;

            /* any k left to do? if so, link onto tree */
            while ( !set_nil(a->completionTree) )
            {     
                  k2 = set_int(a->completionTree);
                  set_rm(k2, a->completionTree);
                  u = NULL;

            TRAV(p->next, k2, &rk2, u);

                  /* any subtrees missing k2 tokens, add u onto end */
                  a->tcontext = tlink(a->tcontext, u, k2);
            Tfree(u);   /* MR10 */
            }
            set_orin(&(a->completionTree), rk2);/* remember what we couldn't do */
            set_free(rk2);
#ifdef DBG_PRED
            fprintf(stderr, "LL(i<%d) context after ruleref:", LL_k);
            preorder(a->tcontext);
            fprintf(stderr, "\n");
#endif
/*          complete_context_trees(p, a->down);*/
      }
#ifdef DBG_PRED
      fprintf(stderr, "exit complete_context_trees\n");
#endif
}

/* Walk a list of predicates and return the set of all tokens in scontext[1]'s */
set
#ifdef __USE_PROTOS
covered_set( Predicate *p )
#else
covered_set( p )
Predicate *p;
#endif
{
      set a;

      a = empty;
      for (; p!=NULL; p=p->right)
      {
            if ( p->expr == PRED_AND_LIST || p->expr == PRED_OR_LIST )
            {
                  set_orin(&a, covered_set(p->down));
                  continue;
            }
            set_orin(&a, p->scontext[1]);
            set_orin(&a, covered_set(p->down));
      }
      return a;
}

/* MR10 predicate_free()
   MR10 Don't free the leaf nodes since they are part of the action node
*/

#ifdef __USE_PROTOS
void predicate_free(Predicate *p)
#else
void predicate_free(p)
  Predicate     *p;
#endif
{
  if (p == NULL) return;
  predicate_free(p->right);
  predicate_free(p->down);
  if (p->cloned ||
      p->source == NULL ||
      p->source->guardpred == NULL ||
      p->expr == PRED_AND_LIST ||
      p->expr == PRED_OR_LIST) {
    set_free(p->scontext[1]);
    set_free(p->completionSet);
    set_free(p->completionTree);
    set_free(p->plainSet);
    Tfree(p->tcontext);
    free( (char *) p);
  } else {
    p->right=NULL;
    p->down=NULL;  /* MR13 *** debug */
  };
}

/* MR10 predicate_dup() */

#ifdef __USE_PROTOS
Predicate * predicate_dup_xxx(Predicate *p,int contextToo)
#else
Predicate * predicate_dup_xxx(p,contextToo)
  Predicate     *p;
  int           contextToo;
#endif
{
  Predicate     *q;

  if (p == NULL) return NULL;
  q=new_pred();
  q->down=predicate_dup(p->down);
  q->right=predicate_dup(p->right);

  /*
     don't replicate expr - it is read-only
     and address comparison is used to look
     for identical predicates.
  */

  q->expr=p->expr;
  q->k=p->k;
  q->source=p->source;
  q->cloned=1;
  q->ampersandStyle=p->ampersandStyle;
  q->inverted=p->inverted;
  q->predEntry=p->predEntry;
  q->plainSet=set_dup(p->plainSet);

  if (contextToo) {
    q->tcontext=tdup(p->tcontext);
    q->scontext[0]=set_dup(p->scontext[0]);
    q->scontext[1]=set_dup(p->scontext[1]);
    q->completionTree=set_dup(p->completionTree);
    q->completionSet=set_dup(p->completionSet);
  };

  /* don't need to dup "redundant" */

  return q;

}

#ifdef __USE_PROTOS
Predicate * predicate_dup_without_context(Predicate *p)
#else
Predicate * predicate_dup_without_context(p)
  Predicate     *p;
#endif
{
  return predicate_dup_xxx(p,0);
}

#ifdef __USE_PROTOS
Predicate * predicate_dup(Predicate *p)
#else
Predicate * predicate_dup(p)
  Predicate     *p;
#endif
{
  return predicate_dup_xxx(p,1);
}


Generated by  Doxygen 1.6.0   Back to index