www.pudn.com > cppcc.rar > dfa_re_node_builder.cc


/*
 *  File:       dfa_re_node_builder.cc
 *              $Id: dfa_re_node_builder.cc,v 1.6 2002/05/27 02:59:27 alec Exp $
 *
 *  Author:     Alec Panoviciu (alecu@email.com)
 *
 *  Comments:
 *
 *  Revision history:
 *
 *  $Log: dfa_re_node_builder.cc,v $
 *  Revision 1.6  2002/05/27 02:59:27  alec
 *  doc update
 *
 *  Revision 1.5  2002/05/22 01:23:12  alec
 *  case sensitivity support
 *
 *  Revision 1.4  2002/05/01 09:18:26  alec
 *  - vBitset fixes
 *  - FOLLOWPOS written (not tested yet)
 *
 *  Revision 1.3  2002/04/30 16:24:38  alec
 *  tested the scanner ptree & vBitVector implementation -> ok
 *
 *  Revision 1.2  2002/04/30 09:22:32  alec
 *  bitset fixes
 *
 *  Revision 1.1  2002/04/29 09:40:01  alec
 *  *** empty log message ***
 *
 */

/* 
  Copyright (C) 2002 Alexandru Panoviciu (alecu@email.com)

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

 */


#include "dfa_re_node_builder.hh"
#include "dfa_source_re.hh"
#include "vbitset.hh"
#include "parse_util.hh"
#include "prop_registry.hh"


ReNode* DfaReNodeBuilder::createOrNode (ReNode *pre,
                                        ReNode *post, const Position &pos)
{
  return new ReOrNode(dynamic_cast(pre),
                      dynamic_cast(post), pos);
}


ReNode* DfaReNodeBuilder::createCatNode (ReNode *pre, ReNode *post,
                                         const Position &pos)
{
  return new ReCatNode(dynamic_cast(pre),
                       dynamic_cast(post), pos);
}


ReNode* DfaReNodeBuilder::createPlusNode (ReNode *in, const Position &pos)
{ // r+ -> rr*
  return new ReCatNode(dynamic_cast(in->clone()),
                       new ReStarNode(dynamic_cast(in), pos),
                       pos);
}


ReNode* DfaReNodeBuilder::createOptionalNode (ReNode *in, const Position &pos)
{ // r? -> r | lambda
  return new ReOrNode(dynamic_cast(in),
                      new ReLambdaNode(pos), pos);
}


ReNode* DfaReNodeBuilder::createStarNode (ReNode *in, const Position &pos)
{
  return new ReStarNode(dynamic_cast(in), pos);
}


ReNode* DfaReNodeBuilder::createStringLiteralNode (const string& s,
                                                   const Position &pos)
{
  if (s.size() == 0) //empty string => lambda
    return new ReLambdaNode(pos);
  else {
    DfaSourceRe *res = new ReCharNode(s[0], pos);
    for (int i = 1; i < s.size(); i++)
      res = new ReCatNode(res, createCharNode(s[i], pos), pos);
    return res;
  }
}


ReNode* DfaReNodeBuilder::createCharListNode (bool negated,
                                    const vector &chars,
                                    const Position &pos)
{
  vBitset chset(256);
  for (int i = 0; i < chars.size(); i++)
    for (int c = chars[i].first; c <= chars[i].last; c++)
      chset[c].set();
  if (negated) chset.flip();

  if (chset.count1() == 0)
    die(formatError(pos, "Character class does not match any character."));
  
  DfaSourceRe *res = NULL;

  bool caseSensitive = registry["CASE_SENSITIVE"];
  
  for (int c = 0; c < 256; c++) 
    if (chset[c].get()) {
      if (!caseSensitive) // avoid unnecesasry duplicate nodes.
        if (isupper(c) && chset[tolower(c)].get()) continue;
      if (res == NULL) res = createCharNode(c, pos);
      else res = new ReOrNode(res, createCharNode(c, pos), pos);
    }
  
  return res;
}


DfaSourceRe* DfaReNodeBuilder::createEotNode (int tokId, const Position &pos)
{
  return new ReEotNode(tokId, pos);
}


DfaSourceRe* DfaReNodeBuilder::createCharNode (unsigned char match,
                                               const Position &pos)
{
  if (!registry["CASE_SENSITIVE"])
  {
    if (isupper(match)) return new ReOrNode(new ReCharNode(match, pos),
                                            new ReCharNode(tolower( match),
                                                           pos),
                                            pos);
    if (islower(match)) return new ReOrNode(new ReCharNode(match, pos),
                                            new ReCharNode(toupper( match),
                                                           pos),
                                            pos);
  }
  return new ReCharNode(match, pos);
}