Example #1
0
bool check_exp(const node* p, int rr_level)
{
	if (!p || p->t == nt_num) return true;
	// rrlvl1: 交换率,以下两个判断保证了A+B+C+...+Z这种形式下,只选择A>B>C>...>Z这一种组合
	if (rr_level >= 1)
	{
		if (commulative(p->op))
		{
			double v1 = p->l_child->val();
			double v2 = p->r_child->val();
			if (v1 < v2) return false;
			if (double_equ(v1, v2) && shape_less(p->l_child, p->r_child)) return false;
		}
		if (p->l_child->t == nt_op && p->l_child->op == p->op && associative(p->op))
		{
			double v1 = p->l_child->r_child->val();
			double v2 = p->r_child->val();
			if (v1 < v2) return false;
			if (double_equ(v1, v2) && shape_less(p->l_child->r_child, p->r_child)) return false;
		}
	}

	// rrlvl2: 去除/1和-0。/1可以用*1替换,-0可以用+0替换。
	if (rr_level >= 2)
	{
		if (p->op == L'/' && double_equ(p->r_child->val(), 1)) return false;
		if (p->op == L'-' && double_equ(p->r_child->val(), 0)) return false;
	}

	if (!check_exp(p->l_child, rr_level)) return false;
	if (!check_exp(p->r_child, rr_level)) return false;

	return true;
}
Example #2
0
bool check_bone(const node* p, int rr_level)
{
	if (!p || p->t == nt_num) return true;

	// '_'是连字符,要求右孩子是数,左孩子是数或者也是个'_'
	if (p->op == L'_')
	{
		if (p->r_child->t == nt_op) return false;
		if (p->l_child->t == nt_op && p->l_child->op != L'_') return false;
	}

	if (rr_level >= 1)
	{
		// 交换率:规定两个分支的顺序
		if (commulative(p->op))
		{
			// 不可以在这里判断,在check_exp时对满足交换率的左右子树采用了求值的方法:大值在左
			// if (shape_less(p->l_child, p->r_child, false)) return false;
		}

		// 不能出现 A-B+C A/B*C,应该是A+C-B, A*C/B
		if (p->l_child->t == nt_op && get_pred(p->op) == get_pred(p->l_child->op))
		{
			if (p->op < p->l_child->op) return false;
		}

		// 结合率
		// 不能出现 A+(B+C), A+(B-C), A-(B+C), A-(B-C)这样的情况,乘除类似
		if (p->r_child->t == nt_op && associative(p->op) && get_pred(p->op) == get_pred(p->r_child->op)) return false;
	}

	if (!check_bone(p->l_child, rr_level)) return false;
	if (!check_bone(p->r_child, rr_level)) return false;
	return true;
}
Example #3
0
string DocCompiler::generateBinOp(Tree sig, int opcode, Tree arg1, Tree arg2, int priority)
{
  string s;
  int thisPriority = gBinOpLateqTable[opcode]->fPriority;

  /* Priority parenthesis handling. */
  string lpar = "";
  string rpar = "";

  if((thisPriority < priority) || ((thisPriority == priority) && !associative(opcode)))
  {
    // (a+b)*c or (a/b)/c need parenthesis
    lpar = " \\left(";
    rpar = "\\right) ";
  }

  Type t1 = getCertifiedSigType(arg1);
  Type t2 = getCertifiedSigType(arg2);
  bool intOpDetected = false;

  if((t1->nature() == kInt) && (t2->nature() == kInt))
  {
    intOpDetected = true;
  }

  string op;

  if(!intOpDetected)
  {
    op = gBinOpLateqTable[opcode]->fName;
  }
  else
  {
    switch(opcode)
    {
    case kAdd:
      op = "\\oplus";
      gDocNoticeFlagMap["intplus"] = true;
      break;
    case kSub:
      op = "\\ominus";
      gDocNoticeFlagMap["intminus"] = true;
      break;
    case kMul:
      op = "\\odot";
      gDocNoticeFlagMap["intmult"] = true;
      break;
    case kDiv:
      op = "\\oslash";
      gDocNoticeFlagMap["intdiv"] = true;
      gDocNoticeFlagMap["intcast"] = true; // "$normalize(int(i/j))$" in the notice.
      break;
    default:
      op = gBinOpLateqTable[opcode]->fName;
      break;
    }
  }

  /* LaTeX frac{}{} handling VS general case. */
  if((opcode == kDiv) && (!intOpDetected))
  {
    s = subst("$0\\frac{$1}{$2}$3", lpar, CS(arg1, 0), CS(arg2, 0), rpar);
  }
  else
  {
    s = subst("$0$1 $2 $3$4", lpar, CS(arg1, thisPriority), op, CS(arg2, thisPriority), rpar);
  }

// if (opcode == kMul) {
// gDocNoticeFlagMap["cdot"] = true;
// }

  return generateCacheCode(sig, s);
}