ウォンツテック

そでやまのーと

とりあえず前回作った規則を元にC++でコーディング
(a|b)とか(a+|b)とかa+|b*|cとか((a+|b)|c*)とかを正しくTREEにしてくれた。
次はこの木構造を元にNFAを作成するクラスを作る予定

#include <iostream>
using namespace std;

#define eleft e.child.left
#define eright e.child.right
#define ech e.ch

enum op_t {
  e_union,
  e_concat,
  e_closure,
  e_pclosure,
  e_empty,
  e_char
};

struct Leaf {
  op_t op;
  /*
   * if op == "char", then the param of this union is character
   * , else the param of this union is the struct that represents
   * a left tree and a right tree.
   */
  union Entity {
	char ch;
	struct {
	  Leaf *left;
	  Leaf *right;
	} child;
  } e;
};

class Stree {
  char current;
  char *inspectedStr, *baseStr;
  Leaf *root;

  void perror(const char * ptr);
  char getNextCurrent();
  char getBackCurrent();
  void setNextCurrent();
  Leaf* growTree(Leaf* left, Leaf* right, op_t op);
  Leaf* regexp();
  Leaf* regItr1();
  Leaf* regItr2();
  Leaf* regItr3();
  void showItem(Leaf *leaf, int count);

public:
  Stree(char *setch) {
	inspectedStr = setch;
	baseStr = setch;
	current = *(inspectedStr);
	root = regexp();
  }

  void showAll();
};

inline char Stree::getNextCurrent()
{
  return *(inspectedStr+1);
}

inline char Stree::getBackCurrent()
{
  if (baseStr < (inspectedStr-1))
	return '\0';
  return *(inspectedStr-1);
}

inline void Stree::setNextCurrent()
{
  current = *(++inspectedStr);
}

/*
 * This function is mainly dealing with "union".
 */
Leaf* Stree::regexp()
{
  Leaf *xLeaf, *yLeaf;

  xLeaf = regItr1();

  if (current == '|') {
	setNextCurrent();
	yLeaf = regexp();
	xLeaf = growTree(xLeaf, yLeaf, e_union);
  }

  return xLeaf;
}

/*
 * This function is mainly dealing with "concat".
 */
Leaf* Stree::regItr1()
{
  Leaf *xLeaf, *yLeaf;

  xLeaf = regItr2();

  if (xLeaf == NULL)
	return NULL;

  if (current != '\0' && current != '|' && current != ')') {
	yLeaf = regItr1();
	xLeaf = growTree(xLeaf, yLeaf, e_concat);
  }

  return xLeaf;
}

Leaf* Stree::regItr2()
{
  Leaf *xLeaf;

  xLeaf = regItr3();

  if (xLeaf == NULL)
	return NULL;

  if (current == '*') {
	xLeaf = growTree(xLeaf, NULL, e_closure);
	setNextCurrent();
  } else if (current == '+') {
	xLeaf = growTree(xLeaf, NULL, e_pclosure);
	setNextCurrent();
  }

  return xLeaf;
}

Leaf* Stree::regItr3()
{
  Leaf *xLeaf = new Leaf();
  xLeaf->eleft = NULL;
  xLeaf->eright = NULL;

  if (current == '(') {
	setNextCurrent();
	xLeaf = regexp();
	if (current != ')')
	  perror("parse error");
	else
	  setNextCurrent();
  } else if (isalpha(current)) {
	xLeaf->op = e_char;
	xLeaf->ech = current;
	setNextCurrent();
  } else {
	if (current == '|') {
	  xLeaf->op = e_empty;
	  setNextCurrent();
	} else if (getBackCurrent() == '|'){
	  xLeaf->op = e_empty;
	  setNextCurrent();
	} else if (current == '\0') {
	  return NULL;
	} else {
	  perror("sentence error");
	}
  }

  return xLeaf;
}

Leaf* Stree::growTree(Leaf *left, Leaf *right, op_t op)
{
  Leaf *leaf = new Leaf();
  leaf->op = op;
  leaf->eleft = left;
  leaf->eright = right;

  return leaf;
}

void Stree::showAll()
{
  showItem(root, 0);
}

void Stree::showItem(Leaf *leaf, int count)
{
  if (leaf == NULL)
	return;

  if (leaf->op != e_char) {
	for (int i=0; i<=count; i++)
	  cout << " ";
	cout << "left" << endl;
	showItem(leaf->eleft, count+1);
  }

  for (int i=0; i<=count; i++)
	cout << " ";
  switch (leaf->op) {
  case e_union:
	cout << '|';
	break;
  case e_concat:
	break;
  case e_closure:
	cout << '*';
	break;
  case e_pclosure:
	cout << '+';
	break;
  case e_empty:
	cout << "empty" << endl;;
	return;
  case e_char:
	cout << leaf->ech << endl;;
	return;
  }
  cout << endl;

  for (int i=0; i<=count; i++)
	cout << " ";
  cout << "right" << endl;
  showItem(leaf->eright, count+1);
}

void Stree::perror(const char * ptr)
{
  cout << ptr << endl;
  exit(1);
}

int main(int argc, char **argv)
{
  if (argc != 3) {
	cout << "Usage: Stree (regex string) (checking string)" << endl;
	exit(0);
  }
  char *regex = new char[strlen(argv[1])];
  char *check = new char[strlen(argv[2])];
  strncpy(regex, argv[1], strlen(argv[1]));
  strncpy(check, argv[2], strlen(argv[2]));

  Stree st(regex);
  st.showAll();

  delete regex;
  delete check;

  return 0;
}