Exemple #1
0
void
tree_display (NODE *node)
{
    if (node->type == N_OP) {
	if (node->left) {
	    if (PRECEDENCE(node, node->left)) {
		printf("(");
	    }
	    tree_display(node->left);
	    if (PRECEDENCE(node, node->left)) {
		printf(")");
	    }
	    printf(" %c ", node->val.ch);
	} else {
	    printf("%c", node->val.ch);
	}
	if (PRECEDENCE(node, node->right)) {
	    printf("(");
	}
	tree_display(node->right);
	if (PRECEDENCE(node, node->right)) {
	    printf(")");
	}
    } else {
	printf("%s", node->val.name);
    }
}
Exemple #2
0
const char *
tree_string (NODE *node, int init)
{
    static char buf[1024];
    static int len;

    if (init) {
	len = 0;
    }

    if (node->type == N_OP) {
	if (node->left) {
	    if (PRECEDENCE(node, node->left)) {
		len += sprintf(&buf[len], "(");
	    }
	    tree_string(node->left, 0);
	    if (PRECEDENCE(node, node->left)) {
		len += sprintf(&buf[len], ")");
	    }
	    len += sprintf(&buf[len], " %c ", node->val.ch);
	} else {
	    len += sprintf(&buf[len], "%c", node->val.ch);
	}
	if (PRECEDENCE(node, node->right)) {
	    len += sprintf(&buf[len], "(");
	}
	tree_string(node->right, 0);
	if (PRECEDENCE(node, node->right)) {
	    len += sprintf(&buf[len], ")");
	}
    } else {
	len += sprintf(&buf[len], "%s", node->val.name);
    }
    return buf;
}
Exemple #3
0
static expr *parse_rhs(expr *lhs, int priority)
{
	for(;;){
    int this_pri, next_pri;
		e_op op;
		expr *rhs;

		op = tok_cur;
		if(!is_op(op))
			return lhs; /* eof, rparen and colon covered here */

		this_pri = PRECEDENCE(op);
    if(this_pri > priority)
      return lhs;

		/* eat the op */
		tok_next();

		/* special case for ternary */
		if(op == tok_question){
			expr *if_t = parse();

			if(tok_cur != tok_colon)
				CPP_DIE("colon expected for ternary-? operator");
			tok_next();

			rhs = parse();

			lhs = expr_new_top(lhs, if_t, rhs);
		}else{
			rhs = parse_primary();

			/* now on the next op, or eof (in which case, precedence returns -1 */
			next_pri = PRECEDENCE(tok_cur);
			if(next_pri < this_pri) {
				/* next is tighter, give it our rhs as its lhs */
				rhs = parse_rhs(rhs, next_pri);
			}

			lhs = expr_op(op, lhs, rhs);
		}
  }
}
Exemple #4
0
/****************************************************************************
Desc : Adds an operator to the selection criteria of a given cursor.
****************************************************************************/
FLMEXP RCODE FLMAPI FlmCursorAddOp(
	HFCURSOR		hCursor,
	QTYPES		eOperator,
	FLMBOOL		bResolveUnknown
	)
{
	RCODE			rc = FERR_OK;
	CURSOR *		pCursor = (CURSOR *)hCursor;
	FQNODE *		pTmpQNode;
	FQNODE *		pTmpGraftNode;
	FQNODE *		pTmpChildNode;
	FLMBOOL		bDecrementNestLvl = FALSE;
	FLMUINT		uiFlags = bResolveUnknown ? FLM_RESOLVE_UNK : 0;

	if (!pCursor)
	{
		flmAssert( 0);
		rc = RC_SET( FERR_INVALID_PARM);
		goto Exit;
	}
	if (RC_BAD( rc = pCursor->rc))
	{
		goto Exit;
	}

	// If a read operation has already been performed on this query, no
	// selection criteria may be added.
	
	if (pCursor->bOptimized)
	{
		rc = RC_SET( FERR_ILLEGAL_OP);
		goto Exit;
	}
	
	// If the operator is a left paren, link it as the last sibling in the
	// argument list of the current operator.

	if (eOperator == FLM_LPAREN_OP)
	{
		(pCursor->QTInfo.uiNestLvl)++;
		goto Exit;
	}

	// If it is a right paren, find the left paren and close it out

	if (eOperator == FLM_RPAREN_OP)
	{
		if (!pCursor->QTInfo.uiNestLvl)
		{
			rc = RC_SET( FERR_CURSOR_SYNTAX);
			goto Exit;
		}
		(pCursor->QTInfo.uiNestLvl)--;
		goto Exit;
	}
		
	// If it is not an operator, return an error

	if (!IS_OP( eOperator))
	{
		rc = RC_SET( FERR_CURSOR_SYNTAX);
		goto Exit;
	}

	// If an operator is not expected, bail out

	if (!(pCursor->QTInfo.uiExpecting & FLM_Q_OPERATOR) &&
		 eOperator != FLM_NEG_OP &&
		 eOperator != FLM_NOT_OP)
	{
		rc = RC_SET( FERR_CURSOR_SYNTAX);
		goto Exit;
	}

	// Make a QNODE and find a place for it in the query tree

	if (RC_BAD( rc = flmCurMakeQNode( &pCursor->QueryPool, eOperator,
								NULL, 0, uiFlags, &pTmpQNode)))
	{
		goto Exit;
	}
	pTmpQNode->uiNestLvl = pCursor->QTInfo.uiNestLvl;

	// If this is the first operator in the query, set the current operator
	// to it and graft in the current operand as its child.  NOTE:  there
	// should always be a current operand at this point.

	if (!pCursor->QTInfo.pTopNode)
	{
		pCursor->QTInfo.pTopNode = pTmpQNode;
		pCursor->QTInfo.pCurOpNode = pTmpQNode;
		if (pCursor->QTInfo.pCurAtomNode)
		{

			// If the current operand node is a user predicate, the only
			// thing that can become its parent is a logical operator.

			if (GET_QNODE_TYPE( pCursor->QTInfo.pCurAtomNode) ==
				 FLM_USER_PREDICATE && !IS_LOG_OP( eOperator))
			{
				rc = RC_SET( FERR_CURSOR_SYNTAX);
				goto Exit;
			}
			flmCurLinkLastChild( pTmpQNode, pCursor->QTInfo.pCurAtomNode);
		}
		pCursor->QTInfo.uiExpecting = FLM_Q_OPERAND;
		goto Exit;
	}

	// Go up the stack until an operator whose nest level or precedence is < 
	// this one's is encountered, then link this one in as the last child

	for (pTmpChildNode = NULL, pTmpGraftNode = pCursor->QTInfo.pCurOpNode;
				;
		  pTmpChildNode = pTmpGraftNode, pTmpGraftNode = pTmpGraftNode->pParent)
	{
		if (pTmpGraftNode->uiNestLvl < pTmpQNode->uiNestLvl ||
			 (pTmpGraftNode->uiNestLvl == pTmpQNode->uiNestLvl &&
			  PRECEDENCE( pTmpGraftNode->eOpType) < PRECEDENCE( eOperator)))
		{

			// If the node under which this operator is to be grafted already
			//	has two children, or if its child is at a greater nesting level,
			//	link the child as the last child of this operator.  Example:
			//	((A - B) == C) && (((D + E) * F) == G).
			//	When the '*' operator in this expression is added, it will be
			//	grafted as the last child of the '&&' operator.  But the '+'
			//	must first be unlinked from the '&&' and then linked as the child
			//	of the '*'.  Otherwise, they will be siblings, and the expression
			//	will be evaluated incorrectly.

			if (pTmpChildNode &&
				 (pTmpChildNode->uiNestLvl > pTmpQNode->uiNestLvl ||
				  pTmpChildNode->pPrevSib != NULL ||
				  pTmpGraftNode->eOpType == FLM_NEG_OP ||
				  pTmpGraftNode->eOpType == FLM_NOT_OP))
			{
				flmCurLinkLastChild( pTmpQNode, pTmpChildNode);
			}

			// If this operator is to be grafted into the query tree at the leaf
			//	level, link the current operand as its last child.  Examples:
			//	in A * (B + C), we want B to be linked to +;
			//	in A + B * C, we want B linked to *.

			if (pTmpGraftNode == pCursor->QTInfo.pCurOpNode &&
				 eOperator != FLM_NEG_OP &&
				 eOperator != FLM_NOT_OP)
			{

				// If the current operand node is a user predicate, the only
				// thing that can become its parent is a logical operator.

				if (pCursor->QTInfo.pCurAtomNode &&
					 GET_QNODE_TYPE( pCursor->QTInfo.pCurAtomNode) ==
						FLM_USER_PREDICATE && !IS_LOG_OP( eOperator))
				{
					rc = RC_SET( FERR_CURSOR_SYNTAX);
					goto Exit;
				}
				flmCurLinkLastChild( pTmpQNode, pCursor->QTInfo.pCurAtomNode);
			}
			flmCurLinkLastChild( pTmpGraftNode, pTmpQNode);
			break;
		}
		if (!pTmpGraftNode->pParent)
		{
			pCursor->QTInfo.pTopNode = pTmpQNode;
			flmCurLinkLastChild( pTmpQNode, pTmpGraftNode);
			break;
		}
	}

	pCursor->QTInfo.pCurOpNode = pTmpQNode;
	pCursor->QTInfo.uiExpecting = FLM_Q_OPERAND;

Exit:
	if (bDecrementNestLvl)
	{
		(pCursor->QTInfo.uiNestLvl)--;
	}
	if (pCursor)
	{
		pCursor->rc = rc;
	}
	return( rc);
}