Changed directory structure, changed name of XSLProcessor to XSLTProcessor

git-svn-id: svn://10.0.0.236/trunk@65423 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
kvisco%ziplink.net
2000-04-06 07:47:44 +00:00
parent bc2d60ede1
commit e087ec3f85
67 changed files with 14338 additions and 49 deletions

View File

@@ -0,0 +1,139 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: AdditiveExpr.cpp,v 1.1 2000-04-06 07:44:37 kvisco%ziplink.net Exp $
*/
/**
* Represents a AdditiveExpr, an binary expression that
* performs an additive operation between it's lvalue and rvalue:<BR/>
* + : addition
* - : subtraction
* @author <A HREF="mailto:kvisco@ziplink.net">Keith Visco</A>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:44:37 $
**/
#include "Expr.h"
/**
* Creates a new AdditiveExpr using the default operator (ADDITION)
**/
AdditiveExpr::AdditiveExpr() {
this->op = ADDITION;
this->leftExpr = 0;
this->rightExpr = 0;
} //-- AdditiveExpr
/**
* Creates a new AdditiveExpr using the given operator
**/
AdditiveExpr::AdditiveExpr(Expr* leftExpr, Expr* rightExpr, short op) {
this->op = op;
this->leftExpr = leftExpr;
this->rightExpr = rightExpr;
} //-- AdditiveExpr
AdditiveExpr::~AdditiveExpr() {
delete leftExpr;
delete rightExpr;
} //-- ~AdditiveExpr
/**
* Sets the left side of this AdditiveExpr
**/
void AdditiveExpr::setLeftExpr(Expr* leftExpr) {
this->leftExpr = leftExpr;
} //-- setLeftExpr
/**
* Sets the right side of this AdditiveExpr
**/
void AdditiveExpr::setRightExpr(Expr* rightExpr) {
this->rightExpr = rightExpr;
} //-- setRightExpr
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* AdditiveExpr::evaluate(Node* context, ContextState* cs) {
double rightDbl = Double::NaN;
ExprResult* exprRes = 0;
if ( rightExpr ) {
exprRes = rightExpr->evaluate(context, cs);
if ( exprRes ) rightDbl = exprRes->numberValue();
delete exprRes;
}
double leftDbl = Double::NaN;
if ( leftExpr ) {
exprRes = leftExpr->evaluate(context, cs);
if ( exprRes ) leftDbl = exprRes->numberValue();
delete exprRes;
}
double result = 0;
switch ( op ) {
case SUBTRACTION:
result = leftDbl - rightDbl;
break;
default:
result = leftDbl + rightDbl;
break;
}
return new NumberResult(result);
} //-- evaluate
/**
* Returns the String representation of this Expr.
* @param dest the String to use when creating the String
* representation. The String representation will be appended to
* any data in the destination String, to allow cascading calls to
* other #toString() methods for Expressions.
* @return the String representation of this Expr.
**/
void AdditiveExpr::toString(String& str) {
if ( leftExpr ) leftExpr->toString(str);
else str.append("null");
switch ( op ) {
case SUBTRACTION:
str.append(" - ");
break;
default:
str.append(" + ");
break;
}
if ( rightExpr ) rightExpr->toString(str);
else str.append("null");
} //-- toString

View File

@@ -0,0 +1,150 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: AttributeExpr.cpp,v 1.1 2000-04-06 07:44:41 kvisco%ziplink.net Exp $
*/
#include "Expr.h"
/**
* This class represents a ElementExpr as defined by the XSL
* Working Draft
* @author <a href="mailto:kvisco@ziplink.net">Keith Visco</a>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:44:41 $
**/
//- Constructors -/
AttributeExpr::AttributeExpr() {
this->isWild = MB_FALSE;
} //-- AttributeExpr
AttributeExpr::AttributeExpr(String& name) {
//-- copy name
this->name = name;
this->isWild = MB_FALSE;
} //-- AttributeExpr
/**
* Destructor
**/
AttributeExpr::~AttributeExpr() {
} //-- ~AttributeExpr
//------------------/
//- Public Methods -/
//------------------/
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* AttributeExpr::evaluate(Node* context, ContextState* cs) {
NodeSet* nodeSet = new NodeSet();
if ( !context ) return nodeSet;
NamedNodeMap* atts = context->getAttributes();
if ( atts ) {
for (int i = 0; i < atts->getLength(); i++ ) {
Attr* attr = (Attr*)atts->item(i);
if ( isWild ) nodeSet->add(attr);
else {
String attName = attr->getName();
if ( name.isEqual(attName) ){
nodeSet->add(attr);
}
}
}
}
return nodeSet;
} //-- evaluate
/**
* Returns the default priority of this Pattern based on the given Node,
* context Node, and ContextState.
* If this pattern does not match the given Node under the current context Node and
* ContextState then Negative Infinity is returned.
**/
double AttributeExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
return 0.0;
} //-- getDefaultPriority
/**
* Returns the name of this ElementExpr
* @return the name of this ElementExpr
**/
const String& AttributeExpr::getName() {
return (const String&) this->name;
} //-- getName
void AttributeExpr::setName(const String& name) {
this->name.clear();
this->name.append(name);
} //-- setName
void AttributeExpr::setWild(MBool isWild) {
this->isWild = isWild;
} //-- setWild
//-----------------------------/
//- Methods from NodeExpr.cpp -/
//-----------------------------/
/**
* Returns the type of this NodeExpr
* @return the type of this NodeExpr
**/
short AttributeExpr::getType() {
return NodeExpr::ATTRIBUTE_EXPR;
} //-- getType
/**
* Determines whether this NodeExpr matches the given node within
* the given context
**/
MBool AttributeExpr::matches(Node* node, Node* context, ContextState* cs) {
if ( (node) && (node->getNodeType() == Node::ATTRIBUTE_NODE) ) {
if ( isWild ) return MB_TRUE;
const String nodeName = ((Attr*)node)->getName();
return nodeName.isEqual(this->name);
}
return MB_FALSE;
} //-- matches
/**
* Returns the String representation of this NodeExpr.
* @param dest the String to use when creating the String
* representation. The String representation will be appended to
* any data in the destination String, to allow cascading calls to
* other #toString() methods for Expressions.
* @return the String representation of this NodeExpr.
**/
void AttributeExpr::toString(String& dest) {
dest.append('@');
if (isWild) dest.append('*');
else dest.append(this->name);
} //-- toString

View File

@@ -0,0 +1,99 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: AttributeValueTemplate.cpp,v 1.1 2000-04-06 07:44:42 kvisco%ziplink.net Exp $
*/
/**
* AttributeValueTemplate
* @author <a href="mailto:kvisco@ziplink.net">Keith Visco</a>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:44:42 $
**/
#include "Expr.h"
/**
* Create a new AttributeValueTemplate
**/
AttributeValueTemplate::AttributeValueTemplate() {};
/**
* Default destructor
**/
AttributeValueTemplate::~AttributeValueTemplate() {
ListIterator* iter = expressions.iterator();
while ( iter->hasNext() ) {
iter->next(); //advance iterator to allow remove
Expr* expr = (Expr*)iter->remove();
delete expr;
}
delete iter;
} //-- ~AttributeValueTemplate
/**
* Adds the given Expr to this AttributeValueTemplate
**/
void AttributeValueTemplate::addExpr(Expr* expr) {
if (expr) expressions.add(expr);
} //-- addExpr
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* AttributeValueTemplate::evaluate(Node* context, ContextState* cs) {
ListIterator* iter = expressions.iterator();
String result;
while ( iter->hasNext() ) {
Expr* expr = (Expr*)iter->next();
ExprResult* exprResult = expr->evaluate(context, cs);
exprResult->stringValue(result);
delete exprResult;
}
delete iter;
return new StringResult(result);
} //-- evaluate
/**
* Returns the String representation of this Expr.
* @param dest the String to use when creating the String
* representation. The String representation will be appended to
* any data in the destination String, to allow cascading calls to
* other #toString() methods for Expressions.
* @return the String representation of this Expr.
**/
void AttributeValueTemplate::toString(String& str) {
ListIterator* iter = expressions.iterator();
while ( iter->hasNext() ) {
str.append('{');
Expr* expr = (Expr*)iter->next();
expr->toString(str);
str.append('}');
}
delete iter;
} //-- toString

View File

@@ -0,0 +1,139 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: BasicNodeExpr.cpp,v 1.1 2000-04-06 07:44:45 kvisco%ziplink.net Exp $
*/
#include "Expr.h"
/**
* @author <a href="mailto:kvisco@ziplink.net">Keith Visco</a>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:44:45 $
**/
//- Constructors -/
/**
* Creates a new BasicNodeExpr, which matchs any Node
**/
BasicNodeExpr::BasicNodeExpr() {
this->type = NodeExpr::NODE_EXPR;
} //-- BasicNodeExpr
/**
* Creates a new BasicNodeExpr of the given type
**/
BasicNodeExpr::BasicNodeExpr(NodeExpr::NodeExprType nodeExprType) {
this->type = nodeExprType;
} //-- BasicNodeExpr
/**
* Destroys this NodeExpr
**/
BasicNodeExpr::~BasicNodeExpr() {};
//------------------/
//- Public Methods -/
//------------------/
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* BasicNodeExpr::evaluate(Node* context, ContextState* cs) {
NodeSet* nodeSet = new NodeSet();
if ( !context ) return nodeSet;
NodeList* nl = context->getChildNodes();
for (int i = 0; i < nl->getLength(); i++ ) {
Node* node = nl->item(i);
if (matches(node, context, cs)) nodeSet->add(node);
}
return nodeSet;
} //-- evaluate
//-----------------------------/
//- Methods from NodeExpr.cpp -/
//-----------------------------/
/**
* Returns the default priority of this Pattern based on the given Node,
* context Node, and ContextState.
* If this pattern does not match the given Node under the current context Node and
* ContextState then Negative Infinity is returned.
**/
double BasicNodeExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
return -0.5;
} //-- getDefaultPriority
/**
* Returns the type of this NodeExpr
* @return the type of this NodeExpr
**/
short BasicNodeExpr::getType() {
return type;
} //-- getType
/**
* Determines whether this NodeExpr matches the given node within
* the given context
**/
MBool BasicNodeExpr::matches(Node* node, Node* context, ContextState* cs) {
if ( !node ) return MB_FALSE;
switch ( type ) {
case NodeExpr::COMMENT_EXPR:
return (MBool) (node->getNodeType() == Node::COMMENT_NODE);
case NodeExpr::PI_EXPR :
return (MBool) (node->getNodeType() == Node::PROCESSING_INSTRUCTION_NODE);
default: //-- node()
break;
}
return MB_TRUE;
} //-- matches
/**
* Returns the String representation of this NodeExpr.
* @param dest the String to use when creating the String
* representation. The String representation will be appended to
* any data in the destination String, to allow cascading calls to
* other #toString() methods for Expressions.
* @return the String representation of this NodeExpr.
**/
void BasicNodeExpr::toString(String& dest) {
switch ( type ) {
case NodeExpr::COMMENT_EXPR:
dest.append("comment()");
break;
case NodeExpr::PI_EXPR :
dest.append("processing-instruction()");
break;
default: //-- node()
dest.append("node()");
break;
}
} //-- toString

View File

@@ -0,0 +1,134 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: BooleanExpr.cpp,v 1.1 2000-04-06 07:44:46 kvisco%ziplink.net Exp $
*/
/**
* Represents a BooleanExpr, a binary expression that
* performs a boolean operation between it's lvalue and rvalue:<BR/>
* @author <a href="mailto:kvisco@ziplink.net">Keith Visco</a>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:44:46 $
**/
#include "Expr.h"
/**
* Creates a new BooleanExpr using the default operator (AND)
**/
BooleanExpr::BooleanExpr() {
this->op = AND;
this->leftExpr = 0;
this->rightExpr = 0;
} //-- BooleanExpr
/**
* Creates a new BooleanExpr using the given operator
**/
BooleanExpr::BooleanExpr(Expr* leftExpr, Expr* rightExpr, short op) {
this->op = op;
this->leftExpr = leftExpr;
this->rightExpr = rightExpr;
} //-- BooleanExpr
BooleanExpr::~BooleanExpr() {
delete leftExpr;
delete rightExpr;
} //-- ~BooleanExpr
/**
* Sets the left side of this AdditiveExpr
**/
void BooleanExpr::setLeftExpr(Expr* leftExpr) {
this->leftExpr = leftExpr;
} //-- setLeftExpr
/**
* Sets the right side of this AdditiveExpr
**/
void BooleanExpr::setRightExpr(Expr* rightExpr) {
this->rightExpr = rightExpr;
} //-- setRightExpr
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* BooleanExpr::evaluate(Node* context, ContextState* cs) {
MBool lval = MB_FALSE;
ExprResult* exprRes = 0;
if ( leftExpr ) {
exprRes = leftExpr->evaluate(context, cs);
if ( exprRes ) lval = exprRes->booleanValue();
delete exprRes;
}
//-- check left expression for early decision
if (( op == OR ) && (lval)) return new BooleanResult(MB_TRUE);
else if (!lval) return new BooleanResult(MB_FALSE);
MBool rval = MB_FALSE;
if ( rightExpr ) {
exprRes = rightExpr->evaluate(context, cs);
if ( exprRes ) rval = exprRes->booleanValue();
delete exprRes;
}
//-- just use rval, since we already checked lval
return new BooleanResult(rval);
} //-- evaluate
/**
* Returns the String representation of this Expr.
* @param dest the String to use when creating the String
* representation. The String representation will be appended to
* any data in the destination String, to allow cascading calls to
* other #toString() methods for Expressions.
* @return the String representation of this Expr.
**/
void BooleanExpr::toString(String& str) {
if ( leftExpr ) leftExpr->toString(str);
else str.append("null");
switch ( op ) {
case OR:
str.append(" or ");
break;
default:
str.append(" and ");
break;
}
if ( rightExpr ) rightExpr->toString(str);
else str.append("null");
} //-- toString

View File

@@ -0,0 +1,103 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: BooleanFunctionCall.cpp,v 1.1 2000-04-06 07:44:53 kvisco%ziplink.net Exp $
*/
#include "FunctionLib.h"
/**
* Creates a default BooleanFunctionCall, which always evaluates to False
* @author <A HREF="mailto:kvisco@ziplink.net">Keith Visco</A>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:44:53 $
**/
BooleanFunctionCall::BooleanFunctionCall() : FunctionCall(XPathNames::FALSE_FN) {
this->type = FALSE;
} //-- BooleanFunctionCall
/**
* Creates a BooleanFunctionCall of the given type
**/
BooleanFunctionCall::BooleanFunctionCall(short type) : FunctionCall()
{
switch ( type ) {
case BOOLEAN :
FunctionCall::setName(XPathNames::BOOLEAN_FN);
break;
case NOT :
FunctionCall::setName(XPathNames::NOT_FN);
break;
case TRUE :
FunctionCall::setName(XPathNames::TRUE_FN);
break;
default:
FunctionCall::setName(XPathNames::FALSE_FN);
break;
}
this->type = type;
} //-- BooleanFunctionCall
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* BooleanFunctionCall::evaluate(Node* context, ContextState* cs) {
BooleanResult* result = new BooleanResult();
ListIterator* iter = params.iterator();
int argc = params.getLength();
Expr* param = 0;
String err;
switch ( type ) {
case BOOLEAN :
if ( requireParams(1,1,cs) ) {
param = (Expr*)iter->next();
ExprResult* exprResult = param->evaluate(context, cs);
result->setValue(exprResult->booleanValue());
delete exprResult;
}
break;
case NOT :
if ( requireParams(1,1,cs) ) {
param = (Expr*)iter->next();
ExprResult* exprResult = param->evaluate(context, cs);
result->setValue(!exprResult->booleanValue());
delete exprResult;
}
break;
case TRUE :
result->setValue(MB_TRUE);
break;
default:
result->setValue(MB_FALSE);
break;
}
delete iter;
return result;
} //-- evaluate

View File

@@ -0,0 +1,97 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: BooleanResult.cpp,v 1.1 2000-04-06 07:45:19 kvisco%ziplink.net Exp $
*/
/**
* Boolean Expression result
* @author <A href="mailto:kvisco@ziplink.net">Keith Visco</A>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:19 $
**/
#include "ExprResult.h"
/**
* Default Constructor
**/
BooleanResult::BooleanResult() {
value = MB_FALSE;
} //-- BooleanResult
BooleanResult::BooleanResult(const BooleanResult& boolResult) {
this->value = boolResult.getValue();
} //-- BooleanResult
/**
* Creates a new BooleanResult with the value of the given MBool parameter
* @param boolean the MBool to use for initialization of this BooleanResult's value
**/
BooleanResult::BooleanResult(MBool boolean) {
this->value = boolean;
} //-- BooleanResult
/**
* Returns the value of this BooleanResult
* @return the value of this BooleanResult
**/
MBool BooleanResult::getValue() const {
return this->value;
} //-- getValue
/**
* Sets the value of this BooleanResult
* @param boolean the MBool to use for this BooleanResult's value
**/
void BooleanResult::setValue(MBool boolean) {
this->value = boolean;
} //-- setValue
/**
* Sets the value of this BooleanResult
* @param boolResult the BooleanResult to use for setting this BooleanResult's value
**/
void BooleanResult::setValue(const BooleanResult& boolResult) {
this->value = boolResult.getValue();
} //-- setValue
/*
* Virtual Methods from ExprResult
*/
short BooleanResult::getResultType() {
return ExprResult::BOOLEAN;
} //-- getResultType
void BooleanResult::stringValue(String& str) {
if ( value ) str.append("true");
else str.append("false");
} //-- toString
MBool BooleanResult::booleanValue() {
return this->value;
} //-- toBoolean
double BooleanResult::numberValue() {
return ( value ) ? 1.0 : 0.0;
} //-- toNumber

View File

@@ -0,0 +1,144 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: ElementExpr.cpp,v 1.1 2000-04-06 07:45:22 kvisco%ziplink.net Exp $
*/
#include "Expr.h"
/**
* This class represents a ElementExpr as defined by XPath 1.0
* proposed recommendation
* @author <A HREF="mailto:kvisco@mitre.org">Keith Visco</A>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:22 $
**/
//- Constructors -/
ElementExpr::ElementExpr() {
//-- do nothing
} //-- ElementExpr
ElementExpr::ElementExpr(String& name) {
//-- copy name
this->name = name;
} //-- ElementExpr
/**
* Destructor
**/
ElementExpr::~ElementExpr() {
} //-- ~ElementExpr
//------------------/
//- Public Methods -/
//------------------/
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* ElementExpr::evaluate(Node* context, ContextState* cs) {
NodeSet* nodeSet = new NodeSet();
if ( !context ) return nodeSet;
NodeList* nl = context->getChildNodes();
for (int i = 0; i < nl->getLength(); i++ ) {
Node* node = nl->item(i);
if ( node->getNodeType() == Node::ELEMENT_NODE ) {
String tagName = node->getNodeName();
if ( name.isEqual(tagName) ){
nodeSet->add(node);
}
}
}
return nodeSet;
} //-- evaluate
/**
* Returns the default priority of this Pattern based on the given Node,
* context Node, and ContextState.
* If this pattern does not match the given Node under the current context Node and
* ContextState then Negative Infinity is returned.
**/
double ElementExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
return 0.0;
} //-- getDefaultPriority
/**
* Returns the name of this ElementExpr
* @return the name of this ElementExpr
**/
const String& ElementExpr::getName() {
return (const String&) this->name;
} //-- getName
void ElementExpr::setName(const String& name) {
this->name.clear();
this->name.append(name);
} //-- setName
//-----------------------------/
//- Methods from NodeExpr.cpp -/
//-----------------------------/
/**
* Returns the type of this NodeExpr
* @return the type of this NodeExpr
**/
short ElementExpr::getType() {
return NodeExpr::ELEMENT_EXPR;
} //-- getType
/**
* Determines whether this NodeExpr matches the given node within
* the given context
**/
MBool ElementExpr::matches(Node* node, Node* context, ContextState* cs) {
if ( node) {
const String nodeName = node->getNodeName();
return nodeName.isEqual(this->name);
}
return MB_FALSE;
} //-- matches
/**
* Returns the String representation of this NodeExpr.
* @param dest the String to use when creating the String
* representation. The String representation will be appended to
* any data in the destination String, to allow cascading calls to
* other #toString() methods for Expressions.
* @return the String representation of this NodeExpr.
**/
void ElementExpr::toString(String& dest) {
dest.append(this->name);
} //-- toString

View File

@@ -0,0 +1,64 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: ErrorFunctionCall.cpp,v 1.1 2000-04-06 07:45:23 kvisco%ziplink.net Exp $
*/
#include "FunctionLib.h"
/**
* @author <A HREF="mailto:kvisco@ziplink.net">Keith Visco</A>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:23 $
**/
/**
* Creates an Error FunctionCall with no error message
**/
ErrorFunctionCall::ErrorFunctionCall() : FunctionCall(XPathNames::ERROR_FN) {};
/**
* Creates an Error FunctionCall with the given error message
**/
ErrorFunctionCall::ErrorFunctionCall
(const String& errorMsg) : FunctionCall(XPathNames::ERROR_FN)
{
//-- copy errorMsg
this->errorMessage = errorMsg;
} //-- ErrorFunctionCall
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* ErrorFunctionCall::evaluate(Node* context, ContextState* cs) {
return new StringResult( errorMessage);
} //-- evaluate
void ErrorFunctionCall::setErrorMessage(String& errorMsg) {
//-- copy errorMsg
this->errorMessage = errorMsg;
} //-- setError

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,698 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
* -- fixed bug with '<=' and '>=' reported by Bob Miller
*
* Bob Miller, Oblix Inc., kbob@oblix.com
* -- fixed bug with single quotes inside double quotes
*
* $Id: ExprLexer.cpp,v 1.1 2000-04-06 07:45:26 kvisco%ziplink.net Exp $
*/
/**
* Lexical analyzer for XPath expressions
* @author <a href="mailto:kvisco@ziplink.net">Keith Visco</a>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:26 $
**/
#include <iostream.h>
#include "ExprLexer.h"
//---------------------------/
//- Implementation of Token -/
//---------------------------/
/**
* Default constructor for Token
**/
Token::Token() {
this->type =0;
} //-- Token;
/**
* Constructor for Token
* @param type, the type of Token being represented
**/
Token::Token(short type) {
this->type = type;
} //-- Token;
/**
* Constructor for Token
* @param value the value of this Token
* @param type, the type of Token being represented
**/
Token::Token(const String& value, short type) {
this->type = type;
//-- make copy of value String
this->value = value;
} //-- Token
Token::Token(UNICODE_CHAR uniChar, short type) {
this->type = type;
this->value.append(uniChar);
} //-- Token
/**
* Copy Constructor
**/
Token::Token(const Token& token) {
this->type = token.type;
this->value = token.value;
} //-- Token
/**
* Destructor for Token
**/
Token::~Token() {
//-- currently nothing is needed
} //-- ~Token
//--------------------------------/
//- Implementation of ExprLexer -/
//-------------------------------/
/*
* Complex Tokens
*/
//-- Nodetype tokens
const String ExprLexer::COMMENT = "comment";
const String ExprLexer::NODE = "node";
const String ExprLexer::PI = "processing-instruction";
const String ExprLexer::TEXT = "text";
//-- boolean
const String ExprLexer::AND = "and";
const String ExprLexer::OR = "or";
//-- multiplicative operators
const String ExprLexer::MODULUS = "mod";
const String ExprLexer::DIVIDE = "div";
/**
* The set of a XSL Expression Tokens
**/
const Token ExprLexer::TOKENS[] = {
//-- Nodetype tokens
Token(ExprLexer::COMMENT, Token::COMMENT),
Token(ExprLexer::NODE, Token::NODE),
Token(ExprLexer::PI, Token::PI),
Token(ExprLexer::TEXT, Token::TEXT),
//-- boolean operators
Token(ExprLexer::AND, Token::AND_OP),
Token(ExprLexer::OR, Token::OR_OP),
//-- multiplicative operators
Token(ExprLexer::MODULUS, Token::MODULUS_OP),
Token(ExprLexer::DIVIDE, Token::DIVIDE_OP)
};
const short ExprLexer::NUMBER_OF_TOKENS = 8;
//---------------/
//- Contructors -/
//---------------/
/**
* Creates a new ExprLexer using the given String
**/
ExprLexer::ExprLexer(const String& pattern) {
firstItem = 0;
lastItem = 0;
tokenCount = 0;
prevToken = 0;
parse(pattern);
currentItem = firstItem;
} //-- ExprLexer
/**
* Destroys this instance of an ExprLexer
**/
ExprLexer::~ExprLexer() {
//-- delete tokens
//cout << "~ExprLexer() - start"<<endl;
currentItem = firstItem;
while ( currentItem ) {
TokenListItem* temp = currentItem->next;
//cout << "deleting token: " << currentItem->token->value << endl;
delete currentItem->token;
delete currentItem;
currentItem = temp;
}
//cout << "~ExprLexer() - done"<<endl;
} //-- ~ExprLexer
int ExprLexer::countAllTokens() {
return tokenCount;
} //-- countAllTokens
int ExprLexer::countRemainingTokens() {
TokenListItem* temp = currentItem;
int c = 0;
while ( temp ) {
++c;
temp = temp->next;
}
return c;
} //-- countRemainingTokens
MBool ExprLexer::hasMoreTokens() {
return (MBool) ( currentItem );
} //-- hasMoreTokens
Token* ExprLexer::nextToken() {
if ( currentItem ) {
Token* token = currentItem->token;
currentItem = currentItem->next;
return token;
}
return 0;
} //-- nextToken
void ExprLexer::pushBack() {
if ( !currentItem ) {
currentItem = lastItem;
}
else currentItem = currentItem->previous;
} //-- pushBack
/*
Token* ExprLexer::lastToken() {
if (lastItem) {
return lastItem->token;
}
return 0;
} //-- lastToken
*/
Token* ExprLexer::peek() {
Token* token = 0;
TokenListItem* tlItem = currentItem;
if (tlItem) token = tlItem->token;
return token;
} //-- peek
Token* ExprLexer::lookAhead(int offset) {
Token* token = 0;
TokenListItem* tlItem = currentItem;
//-- advance to proper offset
for ( int i = 0; i < offset; i++ )
if ( tlItem ) tlItem = currentItem->next;
if (tlItem) token = tlItem->token;
return token;
} //-- lookAhead
void ExprLexer::addToken(Token* token) {
TokenListItem* tlItem = new TokenListItem;
tlItem->token = token;
tlItem->next = 0;
if (lastItem) {
tlItem->previous = lastItem;
lastItem->next = tlItem;
}
if (!firstItem) firstItem = tlItem;
lastItem = tlItem;
prevToken = token;
++tokenCount;
} //-- addToken
/**
* Returns true if the given character represents an Alpha letter
**/
MBool ExprLexer::isAlphaChar(Int32 ch) {
if ((ch >= 'a' ) && (ch <= 'z' )) return MB_TRUE;
if ((ch >= 'A' ) && (ch <= 'Z' )) return MB_TRUE;
return MB_FALSE;
} //-- isAlphaChar
/**
* Returns true if the given character represents a numeric letter (digit)
**/
MBool ExprLexer::isDigit(Int32 ch) {
if ((ch >= '0') && (ch <= '9')) return MB_TRUE;
return MB_FALSE;
} //-- isDigit
/**
* Returns true if the given character is an allowable QName character
**/
MBool ExprLexer::isNCNameChar(Int32 ch) {
if (isDigit(ch) || isAlphaChar(ch)) return MB_TRUE;
return (MBool) ((ch == '.') ||(ch == '_') || (ch == '-'));
} //-- isNCNameChar
/**
* Returns true if the given character is an allowable NCName character
**/
MBool ExprLexer::isQNameChar(Int32 ch) {
return (MBool) (( ch == ':') || isNCNameChar(ch));
} //-- isQNameChar
/**
* Returns true if the given String is a valid XML QName
**/
MBool ExprLexer::isValidQName(String& name) {
int size = name.length();
if ( size == 0 ) return MB_FALSE;
else if ( !isAlphaChar(name.charAt(0))) return MB_FALSE;
else {
for ( int i = 1; i < size; i++) {
if ( ! isQNameChar(name.charAt(i))) return MB_FALSE;
}
}
return MB_TRUE;
} //-- isValidQName
MBool ExprLexer::isOperatorToken(Token* token) {
if ( !token ) return MB_FALSE;
switch ( token->type ) {
//-- boolean operators
case Token::AND_OP:
case Token::OR_OP:
//-- relational operators
case Token::EQUAL_OP:
case Token::NOT_EQUAL_OP:
case Token::LESS_THAN_OP:
case Token::GREATER_THAN_OP:
case Token::LESS_OR_EQUAL_OP:
case Token::GREATER_OR_EQUAL_OP:
//-- additive operators
case Token::ADDITION_OP:
case Token::SUBTRACTION_OP:
//-- multiplicative operators
case Token::DIVIDE_OP:
case Token::MODULUS_OP:
case Token::MULTIPLY_OP:
return MB_TRUE;
default:
break;
}
return MB_FALSE;
} //-- isOperatorToken
MBool ExprLexer::matchDelimiter(UNICODE_CHAR ch) {
short tokenType = 0;
MBool addChar = MB_TRUE;
switch (ch) {
case FORWARD_SLASH :
tokenType = Token::PARENT_OP;
break;
case L_PAREN :
tokenType = Token::L_PAREN;
break;
case R_PAREN :
tokenType = Token::R_PAREN;
break;
case L_BRACKET :
tokenType = Token::L_BRACKET;
break;
case R_BRACKET :
tokenType = Token::R_BRACKET;
break;
case L_ANGLE :
tokenType = Token::LESS_THAN_OP;
break;
case R_ANGLE :
tokenType = Token::GREATER_THAN_OP;
break;
case COMMA :
tokenType = Token::COMMA;
break;
case PERIOD :
tokenType = Token::SELF_NODE;
break;
case EQUAL :
tokenType = Token::EQUAL_OP;
break;
case PLUS :
tokenType = Token::ADDITION_OP;
break;
case HYPHEN :
tokenType = Token::SUBTRACTION_OP;
break;
case VERT_BAR:
tokenType = Token::UNION_OP;
break;
case ASTERIX:
tokenType = Token::WILD_CARD;
break;
case AT_SIGN:
tokenType = Token::AT_SIGN;
break;
case DOLLAR_SIGN:
tokenType = Token::VAR_REFERENCE;
addChar = MB_FALSE;
break;
default:
return MB_FALSE;;
}
Token* token = 0;
if ( addChar ) token = new Token(ch, tokenType);
else token = new Token(tokenType);
addToken(token);
return MB_TRUE;
} //-- matchDelimiter
/**
* Returns true if the value of the given String matches
* an OperatorName
**/
MBool ExprLexer::matchesOperator(String& buffer) {
int index = 0;
while (index < NUMBER_OF_TOKENS) {
Token tok = TOKENS[index++];
if ( tok.value.isEqual(buffer) ) {
if (isOperatorToken( &tok )) return MB_TRUE;
}
}
return MB_FALSE;
} //-- matchesOperator
/**
* Matches the given String to the appropriate Token
* @param buffer the current StringBuffer representing the value of the Token
* @param ch, the current delimiter token
**/
void ExprLexer::matchToken(String& buffer, UNICODE_CHAR ch) {
if ( buffer.length() == 0) return;
Token* match = new Token();
MBool foundMatch = MB_FALSE;
int index = 0;
//-- check previous token
switch(prevToken->type) {
case Token::VAR_REFERENCE :
if ( prevToken->value.length() == 0) {
prevToken->value.append(buffer);
buffer.clear();
return;
}
break;
default:
break;
}
//-- look for next match
while ( !foundMatch && (index < NUMBER_OF_TOKENS) ) {
Token tok = TOKENS[index++];
if ( tok.value.isEqual(buffer) ) {
foundMatch = MB_TRUE;
switch (tok.type) {
//-- NodeType tokens
case Token::COMMENT:
case Token::NODE :
case Token::PI :
case Token::TEXT :
// make sure next delimiter is '('
if ( ch == L_PAREN) {
//-- copy buffer
match->value = buffer;
//-- copy type
match->type = tok.type;
}
break;
case Token::MULTIPLY_OP :
case Token::DIVIDE_OP:
case Token::MODULUS_OP:
switch ( prevToken->type ) {
case Token::AT_SIGN :
case Token::NULL_TOKEN:
case Token::L_PAREN:
case Token::L_BRACKET:
foundMatch = MB_FALSE;
break; //-- do not match
default:
if ( isOperatorToken(prevToken) ) {
foundMatch = MB_FALSE;
break; //-- do not match
}
match->value = buffer;
match->type = tok.type;
}
break;
default :
//-- copy buffer
match->value = buffer;
match->type = tok.type;
break;
}
} //-- if equal
} //-- while
if (!foundMatch) {
//-- copy buffer
match->value = buffer;
//-- look for function name
if ( ch == L_PAREN) match->type = Token::FUNCTION_NAME;
else match->type = Token::CNAME;
}
addToken(match);
buffer.clear();
} //-- matchToken
/**
* Parses the given String into the set of Tokens
**/
void ExprLexer::parse(const String& pattern) {
String tokenBuffer;
UNICODE_CHAR inLiteral = '\0';
MBool inNumber = MB_FALSE;
Int32 currentPos = 0;
UNICODE_CHAR ch = '\0';
UNICODE_CHAR prevCh = ch;
//-- initialize previous token, this will automatically get
//-- deleted when it goes out of scope
Token nullToken('\0', Token::NULL_TOKEN);
prevToken = &nullToken;
while (currentPos < pattern.length()) {
prevCh = ch;
ch = pattern.charAt(currentPos);
if ( inLiteral ) {
//-- look for end of literal
if ( ch == inLiteral ) {
inLiteral = '\0';
addToken(new Token(tokenBuffer, Token::LITERAL));
tokenBuffer.clear();
}
else {
tokenBuffer.append(ch);
}
}
else if ( inNumber ) {
if (isDigit(ch) || (ch == '.')) {
tokenBuffer.append(ch);
}
else {
inNumber = MB_FALSE;
addToken(new Token(tokenBuffer, Token::NUMBER));
tokenBuffer.clear();
//-- push back last char
--currentPos;
}
}
else if (isDigit(ch)) {
if ((tokenBuffer.length() == 0 ) || matchesOperator(tokenBuffer) ) {
//-- match operator and free up token buffer
matchToken(tokenBuffer, ch);
inNumber = MB_TRUE;
}
else if (( tokenBuffer.length() == 1 ) && (prevCh = '-')) {
inNumber = MB_TRUE;
}
tokenBuffer.append(ch);
}
else {
switch (ch) {
//-- ignore whitespace
case SPACE:
case TAB:
case CR:
case LF:
break;
case S_QUOTE :
case D_QUOTE :
matchToken(tokenBuffer, ch);
inLiteral = ch;
break;
case PERIOD:
if ( inNumber ) tokenBuffer.append(ch);
else if ( prevToken->type == Token::SELF_NODE ) {
prevToken->type = Token::PARENT_NODE;
}
else if ( tokenBuffer.length() > 0 )
tokenBuffer.append(ch);
else matchDelimiter(ch);
break;
case COLON:
if ( prevCh == ch) {
Int32 bufSize = tokenBuffer.length();
tokenBuffer.setLength(bufSize-1);
addToken(new Token(tokenBuffer, Token::AXIS_IDENTIFIER));
tokenBuffer.clear();
}
else tokenBuffer.append(ch);
break;
case FORWARD_SLASH :
matchToken(tokenBuffer, ch);
if ( prevToken->type == Token::PARENT_OP ) {
prevToken->type = Token::ANCESTOR_OP;
prevToken->value.append(ch);
}
else matchDelimiter(ch);
break;
case BANG : //-- used as previous...see EQUAL
matchToken(tokenBuffer,ch);
addToken(new Token(ch, Token::ERROR));
break;
case EQUAL:
switch ( prevCh ) {
case BANG:
prevToken->type = Token::NOT_EQUAL_OP;
prevToken->value.append("=");
break;
case L_ANGLE:
prevToken->type = Token::LESS_OR_EQUAL_OP;
prevToken->value.append("=");
break;
case R_ANGLE:
prevToken->type = Token::GREATER_OR_EQUAL_OP;
prevToken->value.append("=");
break;
default:
matchToken(tokenBuffer, ch);
matchDelimiter(ch);
break;
}
break;
case L_ANGLE :
case R_ANGLE :
matchToken(tokenBuffer, ch);
matchDelimiter(ch);
break;
case HYPHEN :
if ( isValidQName(tokenBuffer) ) tokenBuffer.append(ch);
else {
switch ( prevToken->type ) {
case Token::NULL_TOKEN:
case Token::L_PAREN:
case Token::L_BRACKET:
case Token::COMMA:
inNumber = MB_TRUE;
tokenBuffer.append(ch);
break;
default:
matchToken(tokenBuffer, ch);
matchDelimiter(ch);
break;
}
}
break;
case ASTERIX:
matchToken(tokenBuffer, ch);
switch ( prevToken->type ) {
case Token::PARENT_OP :
case Token::ANCESTOR_OP:
case Token::AT_SIGN :
case Token::NULL_TOKEN:
case Token::L_PAREN:
case Token::L_BRACKET:
matchDelimiter(ch);
break;
default:
if ( isOperatorToken(prevToken) ) {
matchDelimiter(ch);
break; //-- do not match
}
addToken( new Token(ch, Token::MULTIPLY_OP) );
}
break;
case L_PAREN:
case R_PAREN:
case L_BRACKET:
case R_BRACKET:
case COMMA:
case AT_SIGN :
case PLUS:
case DOLLAR_SIGN :
case VERT_BAR:
matchToken(tokenBuffer, ch);
matchDelimiter(ch);
break;
default:
switch (prevCh) {
case SPACE :
case TAB :
case CR :
case LF :
matchToken(tokenBuffer, ch);
tokenBuffer.append(ch);
break;
default:
tokenBuffer.append(ch);
break;
}
break;
}
}
++currentPos;
}
//-- end lexical parsing of current token
//-- freeBuffer if needed
if ( inNumber ) {
addToken(new Token(tokenBuffer, Token::NUMBER));
}
else matchToken(tokenBuffer, ch);
prevToken = 0;
} //-- parse

View File

@@ -0,0 +1,291 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* Larry Fitzpatrick
* -- changed constant short declarations in Token and ExprLexer to
* enumerations, commented with //--LF
*
* $Id: ExprLexer.h,v 1.1 2000-04-06 07:45:29 kvisco%ziplink.net Exp $
*/
#ifndef MITREXSL_EXPRLEXER_H
#define MITREXSL_EXPRLEXER_H
#include "String.h"
#include "baseutils.h"
#include <iostream.h>
/**
* A Token class for the ExprLexer.
* <BR />
* This class was ported from XSL:P, an open source Java based
* XSLT processor, written by yours truly.
* @author <a href="mailto:kvisco@ziplink.net">Keith Visco</a>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:29 $
**/
class Token {
public:
//---------------/
//- Token Types -/
//---------------/
//-- LF - changed from static const short declarations to enum
//-- token types
enum TokenType {
//-- Trivial Tokens
ERROR = 0,
NULL_TOKEN,
LITERAL,
NUMBER,
CNAME,
L_PAREN,
R_PAREN,
L_BRACKET,
R_BRACKET,
COMMA,
FUNCTION_NAME,
WILD_CARD,
AT_SIGN,
VAR_REFERENCE,
PARENT_NODE,
SELF_NODE,
AXIS_IDENTIFIER,
//-------------/
//- operators -/
//-------------/
//-- boolean ops
AND_OP,
OR_OP,
//-- relational
EQUAL_OP,
NOT_EQUAL_OP,
LESS_THAN_OP,
GREATER_THAN_OP,
LESS_OR_EQUAL_OP,
GREATER_OR_EQUAL_OP,
//-- additive operators
ADDITION_OP,
SUBTRACTION_OP,
//-- multiplicative
DIVIDE_OP ,
MULTIPLY_OP,
MODULUS_OP,
//-- path operators
PARENT_OP,
ANCESTOR_OP,
UNION_OP,
//-- node type tokens
COMMENT,
NODE,
PI,
TEXT
};
/**
* Default Constructor
**/
Token();
Token(short type);
Token(const String& value, short type);
Token(UNICODE_CHAR uniChar, short type);
/**
* Copy Constructor
**/
Token(const Token& token);
~Token();
String value;
short type;
}; //--Token
/**
* A class for splitting an "Expr" String into tokens and
* performing basic Lexical Analysis.
*
* <BR>This class was ported from XSL:P, an open source Java based XSL processor
* @author <a href="mailto:kvisco@mitre.org">Keith Visco</a>
**/
class ExprLexer {
public:
/*
* Trivial Tokens
*/
//-- LF, changed to enum
enum _TrivialTokens {
D_QUOTE = '\"',
S_QUOTE = '\'',
L_PAREN = '(',
R_PAREN = ')',
L_BRACKET = '[',
R_BRACKET = ']',
L_ANGLE = '<',
R_ANGLE = '>',
COMMA = ',',
PERIOD = '.',
ASTERIX = '*',
FORWARD_SLASH = '/',
EQUAL = '=',
BANG = '!',
VERT_BAR = '|',
AT_SIGN = '@',
DOLLAR_SIGN = '$',
PLUS = '+',
HYPHEN = '-',
COLON = ':',
//-- whitespace tokens
SPACE = ' ',
TAB = '\t',
CR = '\n',
LF = '\r'
};
/*
* Complex Tokens
*/
//-- Nodetype tokens
static const String COMMENT;
static const String NODE;
static const String PI;
static const String TEXT;
//-- boolean
static const String AND;
static const String OR;
//-- Multiplicative
static const String MODULUS;
static const String DIVIDE;
/*
* Default Token Set
*/
static const Token TOKENS[];
static const short NUMBER_OF_TOKENS;
/**
* Constructor for ExprLexer
**/
ExprLexer(const String& pattern);
~ExprLexer();
/**
* Counts the total number of tokens in this Lexer, even if the token
* has already been seen
* @return the total number of tokens in this Lexer
**/
int countAllTokens();
/**
* Counts the remaining number of tokens in this Lexer
* @return the number of remaining tokens in this Lexer
**/
int countRemainingTokens();
/**
* Returns the type of token that was last return by a call to nextToken
**/
Token* lookAhead(int offset);
Token* nextToken();
Token* peek();
void pushBack();
MBool hasMoreTokens();
MBool isOperatorToken(Token* token);
private:
struct TokenListItem {
Token* token;
TokenListItem* next;
TokenListItem* previous;
};
TokenListItem* currentItem;
TokenListItem* firstItem;
TokenListItem* lastItem;
int tokenCount;
Token* prevToken;
void addToken(Token* token);
/**
* Returns true if the given character represents an Alpha letter
**/
static MBool isAlphaChar(Int32 ch);
/**
* Returns true if the given character represents a numeric letter (digit)
**/
static MBool isDigit(Int32 ch);
/**
* Returns true if the given character is an allowable QName character
**/
static MBool isQNameChar(Int32 ch);
/**
* Returns true if the given character is an allowable NCName character
**/
static MBool isNCNameChar(Int32 ch);
/**
* Returns true if the given String is a valid XML QName
**/
static MBool isValidQName(String& name);
MBool matchDelimiter(UNICODE_CHAR ch);
/**
* Returns true if the value of the given String matches
* an OperatorName
**/
MBool matchesOperator(String& buffer);
/**
* Matches the given String to the appropriate Token
* @param buffer the current StringBuffer representing the value of the Token
* @param ch, the current delimiter token
**/
void matchToken(String& buffer, UNICODE_CHAR ch);
void parse(const String& pattern);
}; //-- ExprLexer
#endif

View File

@@ -0,0 +1,905 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
* Olivier Gerardin, ogerardin@vo.lu
* -- fixed a bug in CreateExpr (@xxx=/yyy was parsed as
* @xxx=@xxx/yyy)
*
* $Id: ExprParser.cpp,v 1.1 2000-04-06 07:45:29 kvisco%ziplink.net Exp $
*/
/**
* ExprParser
* This class is used to parse XSL Expressions
* @author <A HREF="mailto:kvisco@ziplink.net">Keith Visco</A>
* @see ExprLexer
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:29 $
**/
#include "ExprParser.h"
const String ExprParser::L_CURLY_BRACE = "{";
const String ExprParser::R_CURLY_BRACE = "}";
/**
* Creates a new ExprParser
**/
ExprParser::ExprParser() {};
/**
* Default Destructor
**/
ExprParser::~ExprParser() {};
/**
* Creates an Attribute Value Template using the given value
**/
AttributeValueTemplate* ExprParser::createAttributeValueTemplate
(const String& attValue)
{
AttributeValueTemplate* avt = new AttributeValueTemplate();
Int32 size = attValue.length();
int cc = 0;
String buffer;
MBool inExpr = MB_FALSE;
MBool inLiteral = MB_FALSE;
char endLiteral = '"';
char prevCh = '\0';
while ( cc < size) {
UNICODE_CHAR ch = attValue.charAt(cc++);
// if in literal just add ch to buffer
if ( inLiteral && (ch != endLiteral) ) {
buffer.append(ch);
prevCh = ch;
continue;
}
switch ( ch ) {
case '\'' :
case '"' :
buffer.append(ch);
if (inLiteral) inLiteral = MB_FALSE;
else {
inLiteral = MB_TRUE;
endLiteral = ch;
}
break;
case '{' :
// Ignore case where we find two { without a }
if (!inExpr) {
//-- clear buffer
if ( buffer.length() > 0) {
avt->addExpr(new StringExpr(buffer));
buffer.clear();
}
inExpr = MB_TRUE;
}
else if (prevCh == ch) {
inExpr = MB_FALSE;
buffer.append(ch);
}
else {
buffer.append(ch); //-- simply append '{'
ch = '\0';
}
break;
case '}':
if (inExpr) {
inExpr = MB_FALSE;
avt->addExpr(createExpr(buffer));
buffer.clear();
//-- change in case another '}' follows
ch = '\0';
}
else if (prevCh != ch) {
if ( buffer.length() > 0) buffer.append('}');
else avt->addExpr(new StringExpr(R_CURLY_BRACE));
}
break;
default:
buffer.append(ch);
break;
}
prevCh = ch;
}
if ( buffer.length() > 0) {
if ( inExpr ) {
//-- error
String errMsg("#error evaluating AttributeValueTemplate. ");
errMsg.append("Missing '}' after: ");
errMsg.append(buffer);
avt->addExpr(new StringExpr(errMsg));
}
else avt->addExpr(new StringExpr(buffer));
}
return avt;
} //-- createAttributeValueTemplate
Expr* ExprParser::createExpr(const String& pattern) {
ExprLexer lexer(pattern);
return createExpr(lexer);
} //-- createExpr
PatternExpr* ExprParser::createPatternExpr(const String& pattern) {
ExprLexer lexer(pattern);
return createUnionExpr(lexer);
} //-- createPatternExpr
LocationStep* ExprParser::createLocationStep(const String& path) {
ExprLexer lexer(path);
LocationStep* lstep = createLocationStep(lexer);
return lstep;
} //-- createLocationPath
//--------------------/
//- Private Methods -/
//-------------------/
/**
* Creates a binary Expr for the given operator
**/
Expr* ExprParser::createBinaryExpr (Expr* left, Expr* right, Token* op) {
if ( !op ) return 0;
switch(op->type) {
//-- additive ops
case Token::ADDITION_OP :
return new AdditiveExpr(left, right, AdditiveExpr::ADDITION);
case Token::SUBTRACTION_OP:
return new AdditiveExpr(left, right, AdditiveExpr::SUBTRACTION);
//-- case boolean ops
case Token::AND_OP:
return new BooleanExpr(left, right, BooleanExpr::AND);
case Token::OR_OP:
return new BooleanExpr(left, right, BooleanExpr::OR);
//-- equality ops
case Token::EQUAL_OP :
return new RelationalExpr(left, right, RelationalExpr::EQUAL);
case Token::NOT_EQUAL_OP :
return new RelationalExpr(left, right, RelationalExpr::NOT_EQUAL);
//-- relational ops
case Token::LESS_THAN_OP:
return new RelationalExpr(left, right, RelationalExpr::LESS_THAN);
case Token::GREATER_THAN_OP:
return new RelationalExpr(left, right, RelationalExpr::GREATER_THAN);
case Token::LESS_OR_EQUAL_OP:
return new RelationalExpr(left, right, RelationalExpr::LESS_OR_EQUAL);
case Token::GREATER_OR_EQUAL_OP:
return new RelationalExpr(left, right, RelationalExpr::GREATER_OR_EQUAL);
//-- multiplicative ops
case Token::DIVIDE_OP :
return new MultiplicativeExpr(left, right, MultiplicativeExpr::DIVIDE);
case Token::MODULUS_OP :
return new MultiplicativeExpr(left, right, MultiplicativeExpr::MODULUS);
case Token::MULTIPLY_OP :
return new MultiplicativeExpr(left, right, MultiplicativeExpr::MULTIPLY);
default:
break;
}
return 0;
//return new ErrorExpr();
} //-- createBinaryExpr
Expr* ExprParser::createExpr(ExprLexer& lexer) {
MBool done = MB_FALSE;
Expr* expr = 0;
Stack exprs;
Stack ops;
while ( lexer.hasMoreTokens() && (!done)) {
Token* tok = lexer.nextToken();
switch ( tok->type ) {
case Token::R_BRACKET:
case Token::R_PAREN:
case Token::COMMA :
lexer.pushBack();
done = MB_TRUE;
break;
case Token::L_PAREN: //-- Grouping Expression
expr = createExpr(lexer);
//-- look for end ')'
if ( lexer.hasMoreTokens() &&
( lexer.nextToken()->type == Token::R_PAREN ) ) break;
else {
//-- error
delete expr;
expr = new StringExpr("missing ')' in expression");
}
break;
case Token::ANCESTOR_OP:
case Token::PARENT_OP:
lexer.pushBack();
if ( !expr ) expr = createPathExpr(lexer);
else {
PathExpr* pathExpr = createPathExpr(lexer);
pathExpr->addPatternExpr(0, (PatternExpr*)expr,
PathExpr::RELATIVE_OP);
expr = pathExpr;
}
//done = MB_TRUE;
break;
case Token::UNION_OP :
{
UnionExpr* unionExpr = createUnionExpr(lexer);
unionExpr->addPathExpr(0, (PathExpr*)expr );
expr = unionExpr;
done = MB_TRUE;
break;
}
case Token::LITERAL :
expr = new StringExpr(tok->value);
break;
case Token::NUMBER:
{
StringResult str(tok->value);
expr = new NumberExpr(str.numberValue());
break;
}
case Token::FUNCTION_NAME:
{
lexer.pushBack();
expr = createFunctionCall(lexer);
break;
}
case Token::VAR_REFERENCE:
expr = new VariableRefExpr(tok->value);
break;
//-- additive ops
case Token::ADDITION_OP:
case Token::DIVIDE_OP:
//-- boolean ops
case Token::AND_OP :
case Token::OR_OP :
//-- equality ops
case Token::EQUAL_OP:
case Token::NOT_EQUAL_OP:
//-- relational ops
case Token::LESS_THAN_OP:
case Token::GREATER_THAN_OP:
case Token::LESS_OR_EQUAL_OP:
case Token::GREATER_OR_EQUAL_OP:
//-- multiplicative ops
case Token::MODULUS_OP:
case Token::MULTIPLY_OP:
case Token::SUBTRACTION_OP:
{
if ( !exprs.empty() ) {
short ttype = ((Token*)ops.peek())->type;
if (precedenceLevel(tok->type) < precedenceLevel(ttype)) {
expr = createBinaryExpr((Expr*)exprs.pop(), expr,
(Token*)ops.pop());
}
}
exprs.push(expr);
ops.push(tok);
expr = 0; // OG, prevent reuse of expr
break;
}
default:
lexer.pushBack();
expr = createPatternExpr(lexer);
break;
}
}
// make sure expr != 0, will this happen?
if (( expr == 0 ) && (!exprs.empty()))
expr = (Expr*) exprs.pop();
while (!exprs.empty() ) {
expr = createBinaryExpr((Expr*)exprs.pop(), expr, (Token*)ops.pop());
}
return expr;
} //-- createExpr
FilterExpr* ExprParser::createFilterExpr(ExprLexer& lexer) {
FilterExpr* filterExpr = new FilterExpr();
Token* tok = lexer.nextToken();
if ( !tok ) return filterExpr;
Expr* expr = 0;
switch ( tok->type ) {
case Token::FUNCTION_NAME :
expr = createFunctionCall(lexer);
filterExpr->setExpr(expr);
break;
case Token::VAR_REFERENCE :
expr = new VariableRefExpr(tok->value);
filterExpr->setExpr(expr);
break;
case Token::L_PAREN:
//-- primary group expr:
expr = createExpr(lexer);
tok = lexer.nextToken();
if ( (!tok) || (tok->type != Token::R_PAREN ) ) {
String errMsg("error: ");
expr->toString(errMsg);
errMsg.append(" - missing ')'");
delete expr; //-- free up current expr
expr = new ErrorFunctionCall(errMsg);
}
filterExpr->setExpr(expr);
break;
case Token::PARENT_NODE :
expr = new ParentExpr();
filterExpr->setExpr(expr);
break;
case Token::SELF_NODE :
expr = new IdentityExpr();
filterExpr->setExpr(expr);
break;
default:
break;
}
//-- handle predicates
parsePredicates(filterExpr, lexer);
return filterExpr;
} //-- createFilterExpr
FunctionCall* ExprParser::createFunctionCall(ExprLexer& lexer) {
if ( !lexer.hasMoreTokens() ) {
//-- should never see this, I hope
return new ErrorFunctionCall("no tokens, invalid function call");
}
FunctionCall* fnCall = 0;
Token* tok = lexer.nextToken();
if ( tok->type != Token::FUNCTION_NAME ) {
return new ErrorFunctionCall("invalid function call");
}
String fnName = tok->value;
//-- compare function names
//-- * we should hash these names for speed
if ( XPathNames::BOOLEAN_FN.isEqual(tok->value) ) {
fnCall = new BooleanFunctionCall(BooleanFunctionCall::BOOLEAN);
}
else if ( XPathNames::CONCAT_FN.isEqual(tok->value) ) {
fnCall = new StringFunctionCall(StringFunctionCall::CONCAT);
}
else if ( XPathNames::CONTAINS_FN.isEqual(tok->value) ) {
fnCall = new StringFunctionCall(StringFunctionCall::CONTAINS);
}
else if ( XPathNames::COUNT_FN.isEqual(tok->value) ) {
fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::COUNT);
}
else if ( XPathNames::FALSE_FN.isEqual(tok->value) ) {
fnCall = new BooleanFunctionCall();
}
else if ( XPathNames::LAST_FN.isEqual(tok->value) ) {
fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::LAST);
}
else if ( XPathNames::LOCAL_NAME_FN.isEqual(tok->value) ) {
fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::LOCAL_NAME);
}
else if ( XPathNames::NAME_FN.isEqual(tok->value) ) {
fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::NAME);
}
else if ( XPathNames::NAMESPACE_URI_FN.isEqual(tok->value) ) {
fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::NAMESPACE_URI);
}
else if ( XPathNames::NOT_FN.isEqual(tok->value) ) {
fnCall = new BooleanFunctionCall(BooleanFunctionCall::NOT);
}
else if ( XPathNames::POSITION_FN.isEqual(tok->value) ) {
fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::POSITION);
}
else if ( XPathNames::STARTS_WITH_FN.isEqual(tok->value) ) {
fnCall = new StringFunctionCall(StringFunctionCall::STARTS_WITH);
}
else if ( XPathNames::STRING_FN.isEqual(tok->value) ) {
fnCall = new StringFunctionCall(StringFunctionCall::STRING);
}
else if ( XPathNames::STRING_LENGTH_FN.isEqual(tok->value) ) {
fnCall = new StringFunctionCall(StringFunctionCall::STRING_LENGTH);
}
else if ( XPathNames::SUBSTRING_FN.isEqual(tok->value) ) {
fnCall = new StringFunctionCall(StringFunctionCall::SUBSTRING);
}
else if ( XPathNames::SUBSTRING_AFTER_FN.isEqual(tok->value) ) {
fnCall = new StringFunctionCall(StringFunctionCall::SUBSTRING_AFTER);
}
else if ( XPathNames::SUBSTRING_BEFORE_FN.isEqual(tok->value) ) {
fnCall = new StringFunctionCall(StringFunctionCall::SUBSTRING_BEFORE);
}
else if ( XPathNames::TRANSLATE_FN.isEqual(tok->value) ) {
fnCall = new StringFunctionCall(StringFunctionCall::TRANSLATE);
}
else if ( XPathNames::TRUE_FN.isEqual(tok->value) ) {
fnCall = new BooleanFunctionCall(BooleanFunctionCall::TRUE);
}
// OG+
else if ( XPathNames::NUMBER_FN.isEqual(tok->value) ) {
fnCall = new NumberFunctionCall(NumberFunctionCall::NUMBER);
}
else if ( XPathNames::ROUND_FN.isEqual(tok->value) ) {
fnCall = new NumberFunctionCall(NumberFunctionCall::ROUND);
}
else if ( XPathNames::CEILING_FN.isEqual(tok->value) ) {
fnCall = new NumberFunctionCall(NumberFunctionCall::CEILING);
}
else if ( XPathNames::FLOOR_FN.isEqual(tok->value) ) {
fnCall = new NumberFunctionCall(NumberFunctionCall::FLOOR);
}
// OG-
else {
//-- create error function() for now, should be ext function
String err = "not a valid function: ";
err.append(tok->value);
fnCall = new ErrorFunctionCall(err);
}
//-- handle parametes
List params;
String* errMsg = parseParameters(&params, lexer);
if (errMsg) {
String err("error with function call, \"");
err.append(fnName);
err.append("\" : ");
err.append(*errMsg);
fnCall = new ErrorFunctionCall(err);
delete errMsg;
}
// copy params
else if (params.getLength() > 0) {
ListIterator* iter = params.iterator();
while ( iter->hasNext() ) fnCall->addParam( (Expr*)iter->next() );
delete iter;
}
return fnCall;
} //-- createFunctionCall
LocationStep* ExprParser::createLocationStep(ExprLexer& lexer) {
LocationStep* lstep = new LocationStep();
short axisIdentifier = LocationStep::CHILD_AXIS;
//-- get Axis Identifier, if present
Token* tok = lexer.peek();
MBool setDefaultAxis = MB_TRUE;
if ( tok->type == Token::AXIS_IDENTIFIER ) {
//-- eat token
lexer.nextToken();
setDefaultAxis = MB_FALSE;
//-- should switch to a hash here for speed if necessary
if ( ANCESTOR_AXIS.isEqual(tok->value) )
axisIdentifier = LocationStep::ANCESTOR_AXIS;
else if ( ANCESTOR_OR_SELF_AXIS.isEqual(tok->value) )
axisIdentifier = LocationStep::ANCESTOR_OR_SELF_AXIS;
else if ( ATTRIBUTE_AXIS.isEqual(tok->value) )
axisIdentifier = LocationStep::ATTRIBUTE_AXIS;
else if ( CHILD_AXIS.isEqual(tok->value) )
axisIdentifier = LocationStep::CHILD_AXIS;
else if ( DESCENDANT_AXIS.isEqual(tok->value) )
axisIdentifier = LocationStep::DESCENDANT_AXIS;
else if ( DESCENDANT_OR_SELF_AXIS.isEqual(tok->value) )
axisIdentifier = LocationStep::DESCENDANT_OR_SELF_AXIS;
else if ( FOLLOWING_AXIS.isEqual(tok->value) )
axisIdentifier = LocationStep::FOLLOWING_AXIS;
else if ( FOLLOWING_SIBLING_AXIS.isEqual(tok->value) )
axisIdentifier = LocationStep::FOLLOWING_SIBLING_AXIS;
else if ( NAMESPACE_AXIS.isEqual(tok->value) )
axisIdentifier = LocationStep::NAMESPACE_AXIS;
else if ( PARENT_AXIS.isEqual(tok->value) )
axisIdentifier = LocationStep::PARENT_AXIS;
else if ( PRECEDING_AXIS.isEqual(tok->value) )
axisIdentifier = LocationStep::PRECEDING_AXIS;
else if ( PRECEDING_SIBLING_AXIS.isEqual(tok->value) )
axisIdentifier = LocationStep::PRECEDING_SIBLING_AXIS;
else if ( SELF_AXIS.isEqual(tok->value) )
axisIdentifier = LocationStep::SELF_AXIS;
//-- child axis is default
else {
//-- handle error gracefully, simply ignore invalid axis and
//-- use default. Add error message when message observer
//-- is implemented
setDefaultAxis = MB_TRUE;
}
}
//-- parse NodeExpr
NodeExpr* nodeExpr = createNodeExpr(lexer);
lstep->setNodeExpr(nodeExpr);
//-- set default axis identifiers
if ((setDefaultAxis) && (nodeExpr)) {
switch ( nodeExpr->getType() ) {
case NodeExpr::ATTRIBUTE_EXPR:
axisIdentifier = LocationStep::ATTRIBUTE_AXIS;
break;
default:
axisIdentifier = LocationStep::CHILD_AXIS;
}
}
lstep->setAxisIdentifier(axisIdentifier);
//-- handle predicates
parsePredicates(lstep, lexer);
//<debug>
//String tmp;
//lstep->toString(tmp);
//cout << "returning LocationStep: "<< tmp <<endl;
//</debug>
return lstep;
} //-- createLocationPath
NodeExpr* ExprParser::createNodeExpr(ExprLexer& lexer) {
//cout << "creating NodeExpr: "<<endl;
if (!lexer.hasMoreTokens() ) cout << "Lexer has no Tokens"<<endl;
if (!lexer.hasMoreTokens() ) return 0;
NodeExpr* nodeExpr = 0;
Token* tok = lexer.nextToken();
//cout << "Token #" << tok->type <<endl;
List params;
String* errMsg = 0;
switch ( tok->type ) {
case Token::CNAME :
nodeExpr = new ElementExpr(tok->value);
break;
case Token::WILD_CARD:
nodeExpr = new WildCardExpr();
break;
case Token::COMMENT:
nodeExpr = new BasicNodeExpr(NodeExpr::COMMENT_EXPR);
errMsg = parseParameters(&params, lexer);
//-- ignore errMsg for now
delete errMsg;
break;
case Token::NODE :
nodeExpr = new BasicNodeExpr();
errMsg = parseParameters(&params, lexer);
//-- ignore errMsg for now
delete errMsg;
break;
case Token::PI :
nodeExpr = new BasicNodeExpr(NodeExpr::PI_EXPR);
errMsg = parseParameters(&params, lexer);
//-- ignore errMsg for now
delete errMsg;
break;
case Token::TEXT :
nodeExpr = new TextExpr();
errMsg = parseParameters(&params, lexer);
//-- ignore errMsg for now
delete errMsg;
break;
case Token::AT_SIGN:
tok = lexer.nextToken();
if ( !tok ) {
//-- handle error
}
else if (tok->type == Token::CNAME) {
nodeExpr = new AttributeExpr(tok->value);
}
else if ( tok->type == Token::WILD_CARD ) {
AttributeExpr* attExpr = new AttributeExpr();
attExpr->setWild(MB_TRUE);
nodeExpr = attExpr;
}
else {
//-- handle error
}
break;
default:
break;
}
return nodeExpr;
} //-- createNodeExpr
/**
* Creates a PathExpr using the given ExprLexer
* @param lexer the ExprLexer for retrieving Tokens
**/
PathExpr* ExprParser::createPathExpr(ExprLexer& lexer) {
//-- check for RootExpr
if ( lexer.countRemainingTokens() == 1 ) {
if ( lexer.peek()->type == Token::PARENT_OP ) {
lexer.nextToken(); //-- eat token
return new RootExpr();
}
}
PathExpr* pathExpr = new PathExpr();
short ancestryOp = PathExpr::RELATIVE_OP;
while ( lexer.hasMoreTokens() ) {
Token* tok = lexer.nextToken();
if ( lexer.isOperatorToken(tok) ) {
lexer.pushBack();
return pathExpr;
}
switch ( tok->type ) {
case Token::R_PAREN:
case Token::R_BRACKET:
case Token::UNION_OP:
lexer.pushBack();
return pathExpr;
case Token::ANCESTOR_OP :
ancestryOp = PathExpr::ANCESTOR_OP;
break;
case Token::PARENT_OP :
ancestryOp = PathExpr::PARENT_OP;
break;
default:
lexer.pushBack();
pathExpr->addPatternExpr(createPatternExpr(lexer), ancestryOp);
ancestryOp = PathExpr::RELATIVE_OP;
break;
}
}
/* <debug> *
String tmp;
pathExpr->toString(tmp);
cout << "creating pathExpr: " << tmp << endl;
/* </debug> */
return pathExpr;
} //-- createPathExpr
/**
* Creates a PatternExpr using the given ExprLexer
* @param lexer the ExprLexer for retrieving Tokens
**/
PatternExpr* ExprParser::createPatternExpr(ExprLexer& lexer) {
PatternExpr* pExpr = 0;
Token* tok = lexer.peek();
if ( isLocationStepToken(tok) ) {
pExpr = createLocationStep(lexer);
}
else if ( isFilterExprToken(tok) ) {
pExpr = createFilterExpr(lexer);
}
else {
cout << "invalid token: " << tok->value << endl;
//-- eat token for now
lexer.nextToken();
}
return pExpr;
} //-- createPatternExpr
/**
* Creates a PathExpr using the given ExprLexer
* @param lexer the ExprLexer for retrieving Tokens
**/
UnionExpr* ExprParser::createUnionExpr(ExprLexer& lexer) {
UnionExpr* unionExpr = new UnionExpr();
while ( lexer.hasMoreTokens() ) {
Token* tok = lexer.nextToken();
switch ( tok->type ) {
case Token::R_PAREN:
case Token::R_BRACKET:
lexer.pushBack();
return unionExpr;
case Token::UNION_OP :
//-- eat token
break;
default:
lexer.pushBack();
unionExpr->addPathExpr(createPathExpr(lexer));
break;
}
}
//String tmp;
//unionExpr->toString(tmp);
//cout << "creating UnionExpr: " << tmp << endl;
return unionExpr;
} //-- createUnionExpr
MBool ExprParser::isFilterExprToken(Token* token) {
if ( !token ) return MB_FALSE;
switch (token->type) {
case Token::LITERAL:
case Token::NUMBER:
case Token::FUNCTION_NAME:
case Token::VAR_REFERENCE:
case Token::L_PAREN: // grouping expr
case Token::PARENT_NODE:
case Token::SELF_NODE :
return MB_TRUE;
default:
return MB_FALSE;
}
} //-- isFilterExprToken
MBool ExprParser::isLocationStepToken(Token* token) {
if (!token) return MB_FALSE;
return ((token->type == Token::AXIS_IDENTIFIER) || isNodeTypeToken(token));
} //-- isLocationStepToken
MBool ExprParser::isNodeTypeToken(Token* token) {
if (!token) return MB_FALSE;
switch ( token->type ) {
case Token::AT_SIGN:
case Token::CNAME:
case Token::WILD_CARD:
case Token::COMMENT:
case Token::NODE :
case Token::PI :
case Token::TEXT :
return MB_TRUE;
default:
return MB_FALSE;
}
} //-- isLocationStepToken
/**
* Using the given lexer, parses the tokens if they represent a predicate list
* If an error occurs a non-zero String pointer will be returned containing the
* error message.
* @param predicateList, the PredicateList to add predicate expressions to
* @param lexer the ExprLexer to use for parsing tokens
* @return 0 if successful, or a String pointer to the error message
**/
String* ExprParser::parsePredicates(PredicateList* predicateList, ExprLexer& lexer) {
String* errorMsg = 0;
Token* tok = lexer.peek();
if ( !tok ) return 0; //-- no predicates
if ( tok->type != Token::L_BRACKET ) return 0; //-- not start of predicate list
lexer.nextToken();
while ( lexer.hasMoreTokens() ) {
tok = lexer.peek();
if(!tok) {
//-- error missing ']'
errorMsg = new String("missing close of predicate expression ']'");
break;
}
if ( tok->type == Token::R_BRACKET) {
lexer.nextToken(); //-- eat ']'
break;
}
Expr* expr = createExpr(lexer);
predicateList->add(expr);
}
return errorMsg;
} //-- parsePredicates
/**
* Using the given lexer, parses the tokens if they represent a parameter list
* If an error occurs a non-zero String pointer will be returned containing the
* error message.
* @param list, the List to add parameter expressions to
* @param lexer the ExprLexer to use for parsing tokens
* @return 0 if successful, or a String pointer to the error message
**/
String* ExprParser::parseParameters(List* list, ExprLexer& lexer) {
String* errorMsg = 0;
Token* tok = lexer.peek();
if ( !tok ) return 0; //-- no params
if ( tok->type != Token::L_PAREN ) return 0; //-- not start of param list
lexer.nextToken(); //-- eat L_PAREN
MBool done = MB_FALSE;
MBool foundSep = MB_FALSE;
while ( lexer.hasMoreTokens() && !done) {
tok = lexer.peek();
switch ( tok->type ) {
case Token::R_PAREN :
if (foundSep) errorMsg = new String("missing expression after ','");
lexer.nextToken(); //-- eat R_PAREN
done = MB_TRUE;
break;
case Token::COMMA: //-- param separator
//-- eat COMMA
lexer.nextToken();
foundSep = MB_TRUE;
break;
default:
if ((list->getLength() > 0) && (!foundSep)) {
errorMsg = new String("missing ',' or ')'");
done = MB_TRUE;
break;
}
foundSep = MB_FALSE;
Expr* expr = createExpr(lexer);
list->add(expr);
break;
}
}
return errorMsg;
} //-- parseParameters
short ExprParser::precedenceLevel(short tokenType) {
switch(tokenType) {
case Token::OR_OP:
return 1;
case Token::AND_OP:
return 2;
//-- equality
case Token::EQUAL_OP:
case Token::NOT_EQUAL_OP:
return 3;
//-- relational
case Token::LESS_THAN_OP:
case Token::GREATER_THAN_OP:
case Token::LESS_OR_EQUAL_OP:
case Token::GREATER_OR_EQUAL_OP:
return 4;
//-- additive operators
case Token::ADDITION_OP:
case Token::SUBTRACTION_OP:
return 5;
//-- multiplicative
case Token::DIVIDE_OP:
case Token::MULTIPLY_OP:
case Token::MODULUS_OP:
return 6;
default:
break;
}
return 0;
} //-- precedenceLevel

View File

@@ -0,0 +1,106 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: ExprParser.h,v 1.1 2000-04-06 07:45:30 kvisco%ziplink.net Exp $
*/
/**
* ExprParser
* This class is used to parse XSL Expressions
* @author <A href="mailto:kvisco@ziplink.net">Keith Visco</A>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:30 $
* @see ExprLexer
**/
#ifndef MITREXSL_EXPRPARSER_H
#define MITREXSL_EXPRPARSER_H
#include "String.h"
#include "ExprLexer.h"
#include "Expr.h"
#include "FunctionLib.h"
#include "List.h"
#include "Stack.h"
#include <iostream.h>
class ExprParser {
public:
static const String R_CURLY_BRACE;
static const String L_CURLY_BRACE;
/**
* Creates a new ExprParser
**/
ExprParser();
/**
* destroys the ExprParser
**/
~ExprParser();
Expr* createExpr (const String& pattern);
PatternExpr* createPatternExpr (const String& pattern);
LocationStep* createLocationStep(const String& path);
/**
* Creates an Attribute Value Template using the given value
**/
AttributeValueTemplate* createAttributeValueTemplate(const String& attValue);
private:
Expr* createBinaryExpr (Expr* left, Expr* right, Token* op);
Expr* createExpr (ExprLexer& lexer);
FilterExpr* createFilterExpr (ExprLexer& lexer);
FunctionCall* createFunctionCall (ExprLexer& lexer);
LocationStep* createLocationStep (ExprLexer& lexer);
NodeExpr* createNodeExpr (ExprLexer& lexer);
PathExpr* createPathExpr (ExprLexer& lexer);
PatternExpr* createPatternExpr (ExprLexer& lexer);
UnionExpr* createUnionExpr (ExprLexer& lexer);
MBool isFilterExprToken (Token* tok);
MBool isLocationStepToken (Token* tok);
MBool isNodeTypeToken (Token* tok);
static short precedenceLevel (short tokenType);
/**
* Using the given lexer, parses the tokens if they represent a predicate list
* If an error occurs a non-zero String pointer will be returned containing the
* error message.
* @param predicateList, the PredicateList to add predicate expressions to
* @param lexer the ExprLexer to use for parsing tokens
* @return 0 if successful, or a String pointer to the error message
**/
String* parsePredicates(PredicateList* predicateList, ExprLexer& lexer);
String* parseParameters(List* list, ExprLexer& lexer);
}; //-- ExprParser
#endif

View File

@@ -0,0 +1,162 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
* Larry Fitzpatrick, OpenText, lef@opentext.com
* -- changed constant short result types to enum
*
* $Id: ExprResult.h,v 1.1 2000-04-06 07:45:30 kvisco%ziplink.net Exp $
*/
#include "MITREObject.h"
#include "String.h"
#include "baseutils.h"
#include "primitives.h"
#ifndef MITREXSL_EXPRRESULT_H
#define MITREXSL_EXPRRESULT_H
/*
* ExprResult
* <BR />
* Classes Represented:
* BooleanResult, ExprResult, NumberResult, StringResult
* <BR/>
* Note: for NodeSet, see NodeSet.h <BR />
* @author <A HREF="mailto:kvisco@ziplink.net">Keith Visco</A>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:30 $
*/
class ExprResult : public MITREObject {
public:
//-- ResultTypes
enum _ResultType {
NODESET = 1,
STRING,
BOOLEAN,
TREE_FRAGMENT,
NUMBER
};
virtual ~ExprResult() {};
/**
* Returns the type of ExprResult represented
* @return the type of ExprResult represented
**/
virtual short getResultType() = 0;
/**
* Creates a String representation of this ExprResult
* @param str the destination string to append the String representation to.
**/
virtual void stringValue(String& str) = 0;
/**
* Converts this ExprResult to a Boolean (MBool) value
* @return the Boolean value
**/
virtual MBool booleanValue() = 0;
/**
* Converts this ExprResult to a Number (double) value
* @return the Number value
**/
virtual double numberValue() = 0;
};
class BooleanResult : public ExprResult {
public:
BooleanResult();
BooleanResult(MBool boolean);
BooleanResult(const BooleanResult& boolResult);
MBool getValue() const;
void setValue(MBool boolean);
void setValue(const BooleanResult& boolResult);
virtual short getResultType();
virtual void stringValue(String& str);
virtual MBool booleanValue();
virtual double numberValue();
private:
MBool value;
};
class NumberResult : public ExprResult {
public:
NumberResult();
NumberResult(double dbl);
NumberResult(const NumberResult& nbrResult);
double getValue() const;
void setValue(double dbl);
void setValue(const NumberResult& nbrResult);
MBool isNaN() const;
virtual short getResultType();
virtual void stringValue(String& str);
virtual MBool booleanValue();
virtual double numberValue();
private:
double value;
};
class StringResult : public ExprResult {
public:
StringResult();
StringResult(String& str);
StringResult(const String& str);
StringResult(const StringResult& strResult);
String& getValue();
void setValue(const String& str);
virtual short getResultType();
virtual void stringValue(String& str);
virtual MBool booleanValue();
virtual double numberValue();
private:
String value;
};
#endif

View File

@@ -0,0 +1,147 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
* Bob Miller, kbob@oblix.com
* -- plugged core leak.
*
* $Id: FilterExpr.cpp,v 1.1 2000-04-06 07:45:30 kvisco%ziplink.net Exp $
*/
#include "Expr.h"
/**
* @author <a href="mailto:kvisco@ziplink.net">Keith Visco</a>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:30 $
**/
//-- Implementation of FilterExpr --/
FilterExpr::FilterExpr() : PredicateList() {
expr = 0;
}
/**
* Creates a new FilterExpr using the given Expr
* @param expr the Expr to use for evaluation
**/
FilterExpr::FilterExpr(Expr* expr) : PredicateList() {
this->expr = expr;
} //-- FilterExpr
/**
* Destroys this FilterExpr, all predicates and the expr will be deleted
**/
FilterExpr::~FilterExpr() {
delete expr;
} //-- ~FilterExpr
/**
* Sets the Expr of this FilterExpr for use during evaluation
* @param expr the Expr to use for evaluation
**/
void FilterExpr::setExpr(Expr* expr) {
this->expr = expr;
} //-- setExpr
//------------------------------------/
//- Virtual methods from PatternExpr -/
//------------------------------------/
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ProcessorState containing the stack information needed
* for evaluation
* @return the result of the evaluation
* @see PatternExpr
**/
ExprResult* FilterExpr::evaluate(Node* context, ContextState* cs) {
if (( !context ) || (! expr )) return new NodeSet;
ExprResult* exprResult = expr->evaluate(context, cs);
NodeSet* nodeSet = 0;
switch (exprResult->getResultType()) {
case ExprResult::NODESET:
nodeSet = (NodeSet*)exprResult;
break;
/*
case ExprResult.TREE_FRAGMENT:
nodeSet = new NodeSet(1);
nodeSet.add(((TreeFragmentResult)exprResult).getValue());
break;
*/
default:
break;
/*
throw new InvalidExprException
("expecting NodeSet or TreeFragment as the result of the "+
"expression: " + primaryExpr);
*/
}
//-- filter nodes (apply predicates)
evaluatePredicates(nodeSet, cs);
return nodeSet;
} //-- evaluate
/**
* Returns the default priority of this Pattern based on the given Node,
* context Node, and ContextState.
* If this pattern does not match the given Node under the current context Node and
* ContextState then Negative Infinity is returned.
**/
double FilterExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
//-- this method will never be called, it's only here since
//-- I made it manditory for PatternExprs I will remove it soon
return Double::NEGATIVE_INFINITY;
} //-- getDefaultPriority
/**
* Determines whether this PatternExpr matches the given node within
* the given context
**/
MBool FilterExpr::matches(Node* node, Node* context, ContextState* cs) {
if ( !expr ) return MB_FALSE;
NodeSet* nodes = (NodeSet*)evaluate(node, cs);
MBool result = (nodes->contains(node));
delete nodes;
return result;
} //-- matches
/**
* Creates a String representation of this Expr
* @param str the destination String to append to
* @see Expr
**/
void FilterExpr::toString(String& str) {
if ( expr ) expr->toString(str);
else str.append("null");
PredicateList::toString(str);
} //-- toString

View File

@@ -0,0 +1,202 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: FunctionCall.cpp,v 1.1 2000-04-06 07:45:30 kvisco%ziplink.net Exp $
*/
#include "FunctionLib.h"
/**
* This class represents a FunctionCall as defined by the XSL Working Draft
* @author <A HREF="mailto:kvisco@ziplink">Keith Visco</A>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:30 $
**/
const String FunctionCall::INVALID_PARAM_COUNT =
"invalid number of parameters for function: ";
//- Constructors -/
/**
* Creates a new FunctionCall
**/
FunctionCall::FunctionCall() {
this->name = "void";
} //-- FunctionCall
/**
* Creates a new FunctionCall with the given function
* Note: The object references in parameters will be deleted when this
* FunctionCall gets destroyed.
**/
FunctionCall::FunctionCall(const String& name) {
//-- copy name
this->name = name;
} //-- FunctionCall
/**
* Creates a new FunctionCall with the given function name and parameter list
* Note: The object references in parameters will be deleted when this
* FunctionCall gets destroyed.
**/
FunctionCall::FunctionCall(const String& name, List* parameters) {
//-- copy name
this->name = name;
if (parameters) {
ListIterator* pIter = parameters->iterator();
while ( pIter->hasNext() ) {
params.add(pIter->next());
}
delete pIter;
}
} //-- FunctionCall
/**
* Destructor
**/
FunctionCall::~FunctionCall() {
ListIterator* iter = params.iterator();
while ( iter->hasNext() ) {
iter->next();
Expr* expr = (Expr*) iter->remove();
delete expr;
}
delete iter;
} //-- ~FunctionCall
//------------------/
//- Public Methods -/
//------------------/
/**
* Adds the given parameter to this FunctionCall's parameter list
* @param expr the Expr to add to this FunctionCall's parameter list
**/
void FunctionCall::addParam(Expr* expr) {
if ( expr ) params.add(expr);
} //-- addParam
/**
* Evaluates the given Expression and converts it's result to a String.
* The value is appended to the given destination String
**/
void FunctionCall::evaluateToString
(Expr* expr, Node* context, ContextState* cs, String& dest)
{
if (!expr) return;
ExprResult* exprResult = expr->evaluate(context, cs);
exprResult->stringValue(dest);
delete exprResult;
} //-- evaluateToString
/**
* Evaluates the given Expression and converts it's result to a number.
**/
double FunctionCall::evaluateToNumber
(Expr* expr, Node* context, ContextState* cs)
{
double result = Double::NaN;
if (!expr) return result;
ExprResult* exprResult = expr->evaluate(context, cs);
result = exprResult->numberValue();
delete exprResult;
return result;
} //-- evaluateToNumber
/**
* Returns the name of this FunctionCall
* @return the name of this FunctionCall
**/
const String& FunctionCall::getName() {
return (const String&) this->name;
} //-- getName
/**
* Called to check number of parameters
**/
MBool FunctionCall::requireParams
(int paramCountMin, int paramCountMax, ContextState* cs)
{
int argc = params.getLength();
if (( argc < paramCountMin) || (argc > paramCountMax)) {
String err(INVALID_PARAM_COUNT);
toString(err);
cs->recieveError(err);
return MB_FALSE;
}
return MB_TRUE;
} //-- requireParams
/**
* Called to check number of parameters
**/
MBool FunctionCall::requireParams(int paramCountMin, ContextState* cs) {
int argc = params.getLength();
if (argc < paramCountMin) {
String err(INVALID_PARAM_COUNT);
toString(err);
cs->recieveError(err);
return MB_FALSE;
}
return MB_TRUE;
} //-- requireParams
/**
* Sets the function name of this FunctionCall
* @param name the name of this Function
**/
void FunctionCall::setName(const String& name) {
this->name.clear();
this->name.append(name);
} //-- setName
/**
* Returns the String representation of this NodeExpr.
* @param dest the String to use when creating the String
* representation. The String representation will be appended to
* any data in the destination String, to allow cascading calls to
* other #toString() methods for Expressions.
* @return the String representation of this NodeExpr.
**/
void FunctionCall::toString(String& dest) {
dest.append(this->name);
dest.append('(');
//-- add parameters
ListIterator* iterator = params.iterator();
int argc = 0;
while ( iterator->hasNext() ) {
if ( argc > 0 ) dest.append(',');
Expr* expr = (Expr*)iterator->next();
expr->toString(dest);
++argc;
}
delete iterator;
dest.append(')');
} //-- toString

View File

@@ -0,0 +1,365 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* Olivier Gerardin, ogerardin@vo.lu
* -- added number functions
*
* $Id: FunctionLib.h,v 1.1 2000-04-06 07:45:30 kvisco%ziplink.net Exp $
*/
#ifndef MITREXSL_FUNCTIONLIB_H
#define MITREXSL_FUNCTIONLIB_H
#include "String.h"
#include "primitives.h"
#include "NodeSet.h"
#include "List.h"
#include "dom.h"
#include "ExprResult.h"
#include "baseutils.h"
#include "Expr.h"
#include "Names.h"
#include "XMLUtils.h"
#include <math.h>
class XPathNames {
public:
//-- Function Names
static const String BOOLEAN_FN;
static const String CONCAT_FN;
static const String CONTAINS_FN;
static const String COUNT_FN ;
static const String FALSE_FN;
static const String LAST_FN;
static const String LOCAL_NAME_FN;
static const String NAME_FN;
static const String NAMESPACE_URI_FN;
static const String NOT_FN;
static const String POSITION_FN;
static const String STARTS_WITH_FN;
static const String STRING_FN;
static const String STRING_LENGTH_FN;
static const String SUBSTRING_FN;
static const String SUBSTRING_AFTER_FN;
static const String SUBSTRING_BEFORE_FN;
static const String TRANSLATE_FN;
static const String TRUE_FN;
// OG+
static const String NUMBER_FN;
static const String ROUND_FN;
static const String CEILING_FN;
static const String FLOOR_FN;
// OG-
//-- internal XSL processor functions
static const String ERROR_FN;
}; //-- XPathNames
/**
* This class represents a FunctionCall as defined by the XSL
* Working Draft.
* This file was ported from XSL:P <BR />
* @author <a href="mailto:kvisco@mitre.org">Keith Visco</a>
* <BR/>
* <PRE>
* Modifications:
* 19990805: Keith Visco
* - added NodeSetFunctionCall
* - moved position() function into NodeSetFunctionCall
* - removed PositionFunctionCall
* 19990806: Larry Fitzpatrick
* - changed constant short declarations for BooleanFunctionCall
* with enumerations
* 19990806: Keith Visco
* - added StringFunctionCall
* - stated using Larry's enum suggestion instead of using static const shorts,
* as you can see, I am a Java developer! ;-)
* </PRE>
**/
class FunctionCall : public Expr {
public:
static const String INVALID_PARAM_COUNT;
virtual ~FunctionCall();
/**
* Adds the given parameter to this FunctionCall's parameter list
* @param expr the Expr to add to this FunctionCall's parameter list
**/
void addParam(Expr* expr);
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs) = 0;
/**
* Returns the name of this FunctionCall
* @return the name of this FunctionCall
**/
const String& getName();
virtual MBool requireParams(int paramCountMin, ContextState* cs);
virtual MBool requireParams(int paramCountMin,
int paramCountMax,
ContextState* cs);
/**
* Sets the function name of this FunctionCall
* @param name the name of this Function
**/
void setName(const String& name);
/**
* Returns the String representation of this Pattern.
* @param dest the String to use when creating the String
* representation. The String representation will be appended to
* any data in the destination String, to allow cascading calls to
* other #toString() methods for Expressions.
* @return the String representation of this Pattern.
**/
virtual void toString(String& dest);
protected:
List params;
FunctionCall();
FunctionCall(const String& name);
FunctionCall(const String& name, List* parameters);
/**
* Evaluates the given Expression and converts it's result to a String.
* The value is appended to the given destination String
**/
void FunctionCall::evaluateToString
(Expr* expr, Node* context, ContextState* cs, String& dest);
/**
* Evaluates the given Expression and converts it's result to a number.
**/
double evaluateToNumber(Expr* expr, Node* context, ContextState* cs);
private:
String name;
}; //-- FunctionCall
/**
* Represents the Set of boolean functions
* @author <a href="mailto:kvisco@mitre.org">Keith Visco</a>
**/
class BooleanFunctionCall : public FunctionCall {
public:
enum _BooleanFunctions { BOOLEAN = 1, FALSE, NOT, TRUE };
/**
* Creates a default BooleanFunctionCall, which always evaluates to False
**/
BooleanFunctionCall();
/**
* Creates a BooleanFunctionCall of the given type
**/
BooleanFunctionCall(short type);
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
private:
short type;
}; //-- BooleanFunctionCall
/**
* Internal Function created when there is an Error during parsing
* an Expression
**/
class ErrorFunctionCall : public FunctionCall {
public:
ErrorFunctionCall();
ErrorFunctionCall(const String& errorMsg);
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
void setErrorMessage(String& errorMsg);
private:
String errorMessage;
}; //-- ErrorFunctionCall
/**
* Represents the XPath NodeSet function calls
**/
class NodeSetFunctionCall : public FunctionCall {
public:
enum _NodeSetFunctions {
COUNT = 1, //-- count()
LAST, //-- last()
LOCAL_NAME, //-- local-name()
NAMESPACE_URI, //-- namespace-uri()
NAME, //-- name()
POSITION //-- position()
};
/**
* Creates a default NodeSetFunction call. Position function is the default.
**/
NodeSetFunctionCall();
/**
* Creates a NodeSetFunctionCall of the given type
**/
NodeSetFunctionCall(short type);
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
private:
short type;
}; //-- NodeSetFunctionCall
/**
* Represents the XPath String Function Calls
**/
class StringFunctionCall : public FunctionCall {
public:
enum _StringFunctions {
CONCAT = 1, //-- concat()
CONTAINS, //-- contains()
NORMALIZE, //-- normalize()
STARTS_WITH, //-- starts-with()
STRING, //-- string()
STRING_LENGTH, //-- string-length()
SUBSTRING, //-- substring()
SUBSTRING_AFTER, //-- substring-after()
SUBSTRING_BEFORE, //-- substring-before()
TRANSLATE //-- translate()
};
/**
* Creates a default String function. String() function is the default.
**/
StringFunctionCall();
/**
* Creates a String function of the given type
**/
StringFunctionCall(short type);
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
private:
short type;
}; //-- StringFunctionCall
// OG+
/**
* Represents the XPath Number Function Calls
**/
class NumberFunctionCall : public FunctionCall {
public:
enum _NumberFunctions {
NUMBER = 1, //-- number()
ROUND, //-- round()
FLOOR, //-- floor()
CEILING //-- ceiling()
};
/**
* Creates a default Number function. number() function is the default.
**/
NumberFunctionCall();
/**
* Creates a Number function of the given type
**/
NumberFunctionCall(short type);
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
private:
short type;
}; //-- NumberFunctionCall
// OG-
#endif

View File

@@ -0,0 +1,59 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: IdentityExpr.cpp,v 1.1 2000-04-06 07:45:31 kvisco%ziplink.net Exp $
*/
/**
* @author <a href="mailto:kvisco@ziplink.net">Keith Visco</a>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:31 $
**/
#include "Expr.h"
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* IdentityExpr::evaluate(Node* context, ContextState* cs) {
NodeSet* nodeSet = new NodeSet();
if ( context ) {
nodeSet->add(context);
}
return nodeSet;
} //-- evaluate
/**
* Returns the String representation of this NodeExpr.
* @param dest the String to use when creating the String
* representation. The String representation will be appended to
* any data in the destination String, to allow cascading calls to
* other #toString() methods for Expressions.
* @return the String representation of this NodeExpr.
**/
void IdentityExpr::toString(String& dest) {
dest.append('.');
} //-- toString

View File

@@ -0,0 +1,317 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: LocationStep.cpp,v 1.1 2000-04-06 07:45:31 kvisco%ziplink.net Exp $
*/
/**
* LocationStep
* @author <a href="mailto:kvisco@ziplink.net">Keith Visco</a>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:31 $
**/
#include "Expr.h"
/**
* Creates a new LocationStep using the default Axis Identifier and no
* NodeExpr (which matches nothing)
**/
LocationStep::LocationStep() : PredicateList() {
nodeExpr = 0;
this->axisIdentifier = CHILD_AXIS;
} //-- LocationStep
/**
* Creates a new LocationStep using the default Axis Identifier and
* the given NodeExpr
* @param nodeExpr the NodeExpr to use when matching Nodes
**/
LocationStep::LocationStep(NodeExpr* nodeExpr) : PredicateList() {
this->nodeExpr = nodeExpr;
this->axisIdentifier = CHILD_AXIS;
} //-- LocationStep
/**
* Creates a new LocationStep using the given NodeExpr and Axis Identifier
* @param nodeExpr the NodeExpr to use when matching Nodes
* @param axisIdentifier the Axis Identifier in which to search for nodes
**/
LocationStep::LocationStep(NodeExpr* nodeExpr, short axisIdentifier) : PredicateList() {
this->nodeExpr = nodeExpr;
this->axisIdentifier = axisIdentifier;
} //-- LocationStep
/**
* Destroys this LocationStep
* All predicates will be deleted
* The NodeExpr will be deleted
**/
LocationStep::~LocationStep() {
delete nodeExpr;
} //-- ~LocationStep
/**
* Sets the Axis Identifier for this LocationStep
* @param axisIdentifier the Axis in which to search for nodes
**/
void LocationStep::setAxisIdentifier(short axisIdentifier) {
this->axisIdentifier = axisIdentifier;
} //-- setAxisIdentifier
/**
* Sets the NodeExpr of this LocationStep for use when matching nodes
* @param nodeExpr the NodeExpr to use when matching nodes
**/
void LocationStep::setNodeExpr(NodeExpr* nodeExpr) {
this->nodeExpr = nodeExpr;
} //-- setNodeExpr
//------------------------------------/
//- Virtual methods from PatternExpr -/
//------------------------------------/
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ProcessorState containing the stack information needed
* for evaluation
* @return the result of the evaluation
* @see PatternExpr
**/
ExprResult* LocationStep::evaluate(Node* context, ContextState* cs) {
NodeSet* nodes = new NodeSet();
if (( !context ) || (! nodeExpr )) return nodes;
Node* node = context;
switch (axisIdentifier) {
case ANCESTOR_AXIS :
if (node) node = context->getParentNode();
//-- do not break here
case ANCESTOR_OR_SELF_AXIS :
while (node) {
if (nodeExpr->matches(node, context, cs)) {
nodes->add(node);
}
node = node->getParentNode();
}
break;
case ATTRIBUTE_AXIS :
{
NamedNodeMap* atts = context->getAttributes();
if ( atts ) {
for ( int i = 0; i < atts->getLength(); i++ ) {
Attr* attr = (Attr*)atts->item(i);
if ( nodeExpr->matches(attr, context, cs) ) nodes->add(attr);
}
}
break;
}
case DESCENDANT_OR_SELF_AXIS :
if ( nodeExpr->matches(context, context, cs))
nodes->add(context);
//-- do not break here
case DESCENDANT_AXIS :
fromDescendants(context, cs, nodes);
break;
case FOLLOWING_AXIS :
{
node = context->getNextSibling();
while (node) {
if (nodeExpr->matches(node, context, cs))
nodes->add(node);
if (node->hasChildNodes())
fromDescendants(node, cs, nodes);
Node* tmpNode = node->getNextSibling();
if (!tmpNode) {
node = node->getParentNode();
if ((node) && (node->getNodeType() != Node::DOCUMENT_NODE))
node = node->getNextSibling();
}
else node = tmpNode;
}
break;
}
case FOLLOWING_SIBLING_AXIS :
node = context->getNextSibling();
while (node) {
if (nodeExpr->matches(node, context, cs))
nodes->add(node);
node = node->getNextSibling();
}
break;
case NAMESPACE_AXIS : //-- not yet implemented
cout << "namespace axis not yet implemented"<<endl;
break;
case PARENT_AXIS :
{
Node* parent = context->getParentNode();
if ( nodeExpr->matches(parent, context, cs) )
nodes->add(parent);
break;
}
case PRECEDING_AXIS :
node = context->getPreviousSibling();
if ( !node ) node = context->getParentNode();
while (node) {
if (nodeExpr->matches(node, context, cs))
nodes->add(node);
Node* temp = node->getPreviousSibling();
if (!temp) node = node->getParentNode();
else node = temp;
}
break;
case PRECEDING_SIBLING_AXIS:
node = context->getPreviousSibling();
while (node) {
if (nodeExpr->matches(node, context, cs))
nodes->add(node);
node = node->getPreviousSibling();
}
break;
case SELF_AXIS :
if ( nodeExpr->matches(context, context, cs) )
nodes->add(context);
break;
default: //-- Children Axis
{
NodeList* nl = context->getChildNodes();
for (int i = 0; i < nl->getLength(); i++ ) {
if ( nodeExpr->matches(nl->item(i), context, cs) )
nodes->add(nl->item(i));
}
break;
}
} //-- switch
//-- apply predicates
evaluatePredicates(nodes, cs);
return nodes;
} //-- evaluate
/**
* Returns the default priority of this Pattern based on the given Node,
* context Node, and ContextState.
* If this pattern does not match the given Node under the current context Node and
* ContextState then Negative Infinity is returned.
**/
double LocationStep::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
if ( !nodeExpr ) {
return Double::NEGATIVE_INFINITY;
}
if (!this->isEmpty()) {
return 0.5;
}
return nodeExpr->getDefaultPriority(node, context, cs);
} //-- getDefaultPriority
void LocationStep::fromDescendants(Node* context, ContextState* cs, NodeSet* nodes) {
if (( !context ) || (! nodeExpr )) return;
NodeList* nl = context->getChildNodes();
for (int i = 0; i < nl->getLength(); i++) {
Node* child = nl->item(i);
if (nodeExpr->matches(child, context, cs))
nodes->add(child);
//-- check childs descendants
if (child->hasChildNodes()) fromDescendants(child, cs, nodes);
}
} //-- fromDescendants
/**
* Determines whether this PatternExpr matches the given node within
* the given context
**/
MBool LocationStep::matches(Node* node, Node* context, ContextState* cs) {
if ( !nodeExpr ) return MB_FALSE;
if ( !nodeExpr->matches(node, context, cs) ) return MB_FALSE;
NodeSet nodes;
nodes.add(node);
evaluatePredicates(&nodes, cs);
return (MBool)(nodes.size() > 0);
} //-- matches
/**
* Creates a String representation of this Expr
* @param str the destination String to append to
* @see Expr
**/
void LocationStep::toString(String& str) {
switch (axisIdentifier) {
case ANCESTOR_AXIS :
str.append("ancestor::");
break;
case ANCESTOR_OR_SELF_AXIS :
str.append("ancestor-or-self::");
break;
case DESCENDANT_AXIS:
str.append("descendant::");
break;
case DESCENDANT_OR_SELF_AXIS:
str.append("descendant-or-self::");
break;
case FOLLOWING_AXIS :
str.append("following::");
break;
case FOLLOWING_SIBLING_AXIS:
str.append("following-sibling::");
break;
case NAMESPACE_AXIS:
str.append("namespace::");
break;
case PARENT_AXIS :
str.append("parent::");
break;
case PRECEDING_AXIS :
str.append("preceding::");
break;
case PRECEDING_SIBLING_AXIS :
str.append("preceding-sibling::");
break;
case SELF_AXIS :
str.append("self::");
break;
default:
break;
}
if ( nodeExpr ) nodeExpr->toString(str);
else str.append("null");
PredicateList::toString(str);
} //-- toString

View File

@@ -0,0 +1,168 @@
target: xpath
CC := $(CC) -g
ROOT_PATH = ..
XML_PATH = $(ROOT_PATH)/xml
DOM_PATH = $(XML_PATH)/dom
BASE_PATH = $(ROOT_PATH)/base
PROCESSOR_PATH = $(ROOT_PATH)/xslt
INCLUDE_PATHS = -I. \
-I$(DOM_PATH) \
-I$(BASE_PATH) \
-I$(XML_PATH) \
-I$(PROCESSOR_PATH) \
-I-
XPATH_OBJS = AdditiveExpr.o \
AttributeExpr.o \
AttributeValueTemplate.o \
BasicNodeExpr.o \
BooleanExpr.o \
BooleanResult.o \
ElementExpr.o \
ExprLexer.o \
ExprParser.o \
FilterExpr.o \
IdentityExpr.o \
LocationStep.o \
MultiplicativeExpr.o \
NodeSet.o \
NumberExpr.o \
NumberResult.o \
PredicateList.o \
ParentExpr.o \
PathExpr.o \
RelationalExpr.o \
RootExpr.o \
StringExpr.o \
StringResult.o \
TextExpr.o \
UnionExpr.o \
VariableRefExpr.o \
WildCardExpr.o \
XPathNames.o
FUNCTION_CALL_OBJS = \
BooleanFunctionCall.o \
ErrorFunctionCall.o \
FunctionCall.o \
NodeSetFunctionCall.o \
NumberFunctionCall.o \
StringFunctionCall.o
ALL_OBJS = $(XPATH_OBJS) \
$(FUNCTION_CALL_OBJS)
xpath: $(ALL_OBJS)
AdditiveExpr.o: Expr.h AdditiveExpr.cpp
$(CC) $(INCLUDE_PATHS) -c AdditiveExpr.cpp
AttributeExpr.o: Expr.h AttributeExpr.cpp
$(CC) $(INCLUDE_PATHS) -c AttributeExpr.cpp
AttributeValueTemplate.o: Expr.h AttributeValueTemplate.cpp
$(CC) $(INCLUDE_PATHS) -c AttributeValueTemplate.cpp
BasicNodeExpr.o: Expr.h BasicNodeExpr.cpp
$(CC) $(INCLUDE_PATHS) -c BasicNodeExpr.cpp
BooleanExpr.o: Expr.h BooleanExpr.cpp
$(CC) $(INCLUDE_PATHS) -c BooleanExpr.cpp
BooleanResult.o: ExprResult.h BooleanResult.cpp
$(CC) $(INCLUDE_PATHS) -c BooleanResult.cpp
ElementExpr.o: Expr.h ElementExpr.cpp
$(CC) $(INCLUDE_PATHS) -c ElementExpr.cpp
ExprLexer.o: ExprLexer.cpp ExprLexer.h
$(CC) $(INCLUDE_PATHS) -c ExprLexer.cpp
ExprParser.o: Expr.h ExprParser.cpp ExprParser.h
$(CC) $(INCLUDE_PATHS) -c ExprParser.cpp
FilterExpr.o: FilterExpr.cpp Expr.h
$(CC) $(INCLUDE_PATHS) -c FilterExpr.cpp
IdentityExpr.o: Expr.h IdentityExpr.cpp
$(CC) $(INCLUDE_PATHS) -c IdentityExpr.cpp
LocationStep.o: Expr.h LocationStep.cpp
$(CC) $(INCLUDE_PATHS) -c LocationStep.cpp
MultiplicativeExpr.o: Expr.h MultiplicativeExpr.cpp
$(CC) $(INCLUDE_PATHS) -c MultiplicativeExpr.cpp
NodeSet.o: NodeSet.h NodeSet.cpp
$(CC) $(INCLUDE_PATHS) -c NodeSet.cpp
NumberExpr.o: Expr.h NumberExpr.cpp
$(CC) $(INCLUDE_PATHS) -c NumberExpr.cpp
NumberResult.o: ExprResult.h NumberResult.cpp
$(CC) $(INCLUDE_PATHS) -c NumberResult.cpp
ParentExpr.o: Expr.h ParentExpr.cpp
$(CC) $(INCLUDE_PATHS) -c ParentExpr.cpp
PathExpr.o: Expr.h PathExpr.cpp
$(CC) $(INCLUDE_PATHS) -c PathExpr.cpp
PredicateList.o: Expr.h PredicateList.cpp
$(CC) $(INCLUDE_PATHS) -c PredicateList.cpp
RelationalExpr.o: Expr.h RelationalExpr.cpp
$(CC) $(INCLUDE_PATHS) -c RelationalExpr.cpp
RootExpr.o: Expr.h RootExpr.cpp
$(CC) $(INCLUDE_PATHS) -c RootExpr.cpp
StringExpr.o: Expr.h StringExpr.cpp
$(CC) $(INCLUDE_PATHS) -c StringExpr.cpp
StringResult.o: ExprResult.h StringResult.cpp
$(CC) $(INCLUDE_PATHS) -c StringResult.cpp
TextExpr.o: Expr.h TextExpr.cpp
$(CC) $(INCLUDE_PATHS) -c TextExpr.cpp
UnionExpr.o: Expr.h UnionExpr.cpp
$(CC) $(INCLUDE_PATHS) -c UnionExpr.cpp
VariableRefExpr.o: Expr.h VariableRefExpr.cpp
$(CC) $(INCLUDE_PATHS) -c VariableRefExpr.cpp
WildCardExpr.o: Expr.h WildCardExpr.cpp
$(CC) $(INCLUDE_PATHS) -c WildCardExpr.cpp
XPathNames.o: FunctionLib.h XPathNames.cpp
$(CC) $(INCLUDE_PATHS) -c XPathNames.cpp
########################
## FunctionCall package
########################
BooleanFunctionCall.o: FunctionLib.h BooleanFunctionCall.cpp
$(CC) $(INCLUDE_PATHS) -c BooleanFunctionCall.cpp
ErrorFunctionCall.o: FunctionLib.h ErrorFunctionCall.cpp
$(CC) $(INCLUDE_PATHS) -c ErrorFunctionCall.cpp
FunctionCall.o: FunctionLib.h FunctionCall.cpp
$(CC) $(INCLUDE_PATHS) -c FunctionCall.cpp
NodeSetFunctionCall.o: FunctionLib.h NodeSetFunctionCall.cpp
$(CC) $(INCLUDE_PATHS) -c NodeSetFunctionCall.cpp
NumberFunctionCall.o: FunctionLib.h NumberFunctionCall.cpp
$(CC) $(INCLUDE_PATHS) -c NumberFunctionCall.cpp
StringFunctionCall.o: FunctionLib.h StringFunctionCall.cpp
$(CC) $(INCLUDE_PATHS) -c StringFunctionCall.cpp

View File

@@ -0,0 +1,146 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: MultiplicativeExpr.cpp,v 1.1 2000-04-06 07:45:32 kvisco%ziplink.net Exp $
*/
/**
* Represents a MultiplicativeExpr, an binary expression that
* performs a multiplicative operation between it's lvalue and rvalue:<BR/>
* * : multiply
* mod : modulus
* div : divide
* @author <A HREF="mailto:kvisco@ziplink.net">Keith Visco</a>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:32 $
**/
#include "Expr.h"
/**
* Creates a new MultiplicativeExpr using the default operator (MULTIPLY)
**/
MultiplicativeExpr::MultiplicativeExpr() {
this->op = MULTIPLY;
this->leftExpr = 0;
this->rightExpr = 0;
} //-- RelationalExpr
/**
* Creates a new MultiplicativeExpr using the given operator
**/
MultiplicativeExpr::MultiplicativeExpr(Expr* leftExpr, Expr* rightExpr, short op) {
this->op = op;
this->leftExpr = leftExpr;
this->rightExpr = rightExpr;
} //-- MultiplicativeExpr
MultiplicativeExpr::~MultiplicativeExpr() {
delete leftExpr;
delete rightExpr;
} //-- ~MultiplicativeExpr
/**
* Sets the left side of this MultiplicativeExpr
**/
void MultiplicativeExpr::setLeftExpr(Expr* leftExpr) {
this->leftExpr = leftExpr;
} //-- setLeftExpr
/**
* Sets the right side of this MultiplicativeExpr
**/
void MultiplicativeExpr::setRightExpr(Expr* rightExpr) {
this->rightExpr = rightExpr;
} //-- setRightExpr
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* MultiplicativeExpr::evaluate(Node* context, ContextState* cs) {
double rightDbl = Double::NaN;
ExprResult* exprRes = 0;
if ( rightExpr ) {
exprRes = rightExpr->evaluate(context, cs);
if ( exprRes ) rightDbl = exprRes->numberValue();
delete exprRes;
}
double leftDbl = Double::NaN;
if ( leftExpr ) {
exprRes = leftExpr->evaluate(context, cs);
if ( exprRes ) leftDbl = exprRes->numberValue();
delete exprRes;
}
double result = 0;
switch ( op ) {
case DIVIDE:
result = (leftDbl / rightDbl);
break;
case MODULUS:
result = fmod(leftDbl, rightDbl);
break;
default:
result = leftDbl * rightDbl;
break;
}
return new NumberResult(result);
} //-- evaluate
/**
* Returns the String representation of this Expr.
* @param dest the String to use when creating the String
* representation. The String representation will be appended to
* any data in the destination String, to allow cascading calls to
* other #toString() methods for Expressions.
* @return the String representation of this Expr.
**/
void MultiplicativeExpr::toString(String& str) {
if ( leftExpr ) leftExpr->toString(str);
else str.append("null");
switch ( op ) {
case DIVIDE:
str.append(" div ");
break;
case MODULUS:
str.append(" mod ");
break;
default:
str.append(" * ");
break;
}
if ( rightExpr ) rightExpr->toString(str);
else str.append("null");
} //-- toString

View File

@@ -0,0 +1,352 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* Larry Fitzpatrick, OpenText, lef@opentext.com
* -- moved initialization of DEFAULT_SIZE from NodeSet.h to here
*
* Olivier Gerardin, ogerardin@vo.lu
* -- fixed numberValue()
*
* $Id: NodeSet.cpp,v 1.1 2000-04-06 07:45:32 kvisco%ziplink.net Exp $
*/
#include "NodeSet.h"
#include <iostream.h>
/**
* NodeSet <BR />
* This class was ported from XSL:P. <BR />
* @author <A HREF="mailto:kvisco@ziplink.net">Keith Visco</A>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:32 $
**/
//-------------/
//- Constants -/
//-------------/
const int NodeSet::DEFAULT_SIZE = 25;
//----------------/
//- Constructors -/
//----------------/
/**
* Creates a new NodeSet with the default Size
**/
NodeSet::NodeSet() {
initialize(DEFAULT_SIZE);
} //-- NodeSet
/**
* Creates a new NodeSet with the default Size
**/
NodeSet::NodeSet(int size) {
initialize(size);
} //-- NodeSet
/**
* Creates a new NodeSet, copying the Node references from the source
* NodeSet
**/
NodeSet::NodeSet(const NodeSet& source) {
initialize(source.size());
source.copyInto(*this);
} //--NodeSet
/**
* Helper method for Constructors
**/
void NodeSet::initialize(int size) {
elements = new Node*[size];
for ( int i = 0; i < size; i++ ) elements[i] = 0;
elementCount = 0;
bufferSize = size;
initialSize = size;
} //-- initialize
/**
* Destructor for NodeSet
**/
NodeSet::~NodeSet() {
delete [] elements;
} //-- ~NodeSet
/**
* Adds the specified Node to this NodeSet if it is not already
* contained within in this NodeSet.
* @param node the Node to add to the NodeSet
* @return true if the Node is added to the NodeSet
**/
MBool NodeSet::add(Node* node) {
if (!contains(node)) {
if (elementCount == bufferSize) increaseSize();
elements[elementCount++] = node;
return MB_TRUE;
}
return MB_FALSE;
} //-- add
/**
* Adds the specified Node to the NodeSet at the specified index,
* as long as the Node is not already contained within the set
* @param node the Node to add to the NodeSet
* @return true if the Node is added to the NodeSet. If the index is
* out of bounds the Node will not be added to the set and false will be returned.
**/
MBool NodeSet::add(int index, Node* node)
{
if ((index < 0) || (index > elementCount)) return MB_FALSE;
if (contains(node)) return MB_FALSE;
// make sure we have room to add the object
if (elementCount == bufferSize) increaseSize();
if (index == elementCount) {
elements[elementCount++] = node;
}
else {
shiftUp(index);
elements[index] = node;
++elementCount;
}
return MB_TRUE;
} //-- add
/**
* Removes all elements from the list
**/
void NodeSet::clear() {
for (int i = 0; i < elementCount; i++) {
elements[i] = 0;
}
elementCount = 0;
} //-- clear
/**
* Returns true if the specified Node is contained in the set.
* if the specfied Node is null, then if the NodeSet contains a null
* value, true will be returned.
* @param node the element to search the NodeSet for
* @return true if specified Node is contained in the NodeSet
**/
MBool NodeSet::contains(Node* node) {
return (MBool)(indexOf(node) >= 0);
} //-- contains
/**
* Copies the elements of this NodeSet, into the destination NodeSet
**/
void NodeSet::copyInto(NodeSet& dest) const {
for ( int i = 0; i < elementCount; i++ ) dest.add(elements[i]);
} //-- copyInto
/**
* Compares the specified object with this NodeSet for equality.
* Returns true if and only if the specified Object is a NodeSet
* that is the same size as this NodeSet and all of its associated
* Nodes are contained within this NodeSet.
* @return true if and only if the specified Object is a NodeSet
* that is the same size as this NodeSet and all of its associated
* Nodes are contained within this NodeSet.
**/
MBool NodeSet::equals(NodeSet* nodeSet) {
if (!nodeSet) return MB_FALSE;
if (nodeSet->size() != size()) return MB_FALSE;
for (int i = 0; i < size(); i++) {
if (!nodeSet->contains(get(i))) return MB_FALSE;
}
return MB_TRUE;
} //-- equals
/**
* Returns the Node at the specified position in this NodeSet.
* @param index the position of the Node to return
**/
Node* NodeSet::get(int index) {
if ((index < 0) || index >= elementCount) return 0;
return elements[index];
} //-- get
/**
* Returns the index of the specified Node,
* or -1 if the Node is not contained in the NodeSet
* @param node the Node to get the index for
**/
int NodeSet::indexOf(Node* node) {
for (int i = 0; i < elementCount; i++)
if (node == elements[i]) return i;
return -1;
} //-- indexOf
/**
* Returns true if there are no Nodes in the NodeSet.
* @return true if there are no Nodes in the NodeSet.
**/
MBool NodeSet::isEmpty() {
return (elementCount == 0) ? MB_TRUE : MB_FALSE;
} //-- isEmpty
/**
* Removes the Node at the specified index from the NodeSet
* @param index the position in the NodeSet to remove the Node from
* @return the Node that was removed from the list
**/
Node* NodeSet::remove(int index) {
if ((index < 0) || (index >= elementCount)) return 0;
Node* node = elements[index];
shiftDown(index+1);
--elementCount;
return node;
} //-- remove
/**
* Removes the the specified Node from the NodeSet
* @param node the Node to remove from the NodeSet
* @return true if the Node was removed from the list
**/
MBool NodeSet::remove(Node* node) {
int index = indexOf(node);
if (index > -1) {
remove(index);
}
else return MB_FALSE;
return MB_TRUE;
} //-- remove
/**
* Returns the number of elements in the NodeSet
* @return the number of elements in the NodeSet
**/
int NodeSet::size() const{
return elementCount;
} //-- size
/**
* Creates a String representation of this NodeSet
* @param str the destination string to append the String representation to.
**/
void NodeSet::toString(String& str) {
str.append("#NodeSet");
} //-- toString
//-------------------/
//- Private Methods -/
//-------------------/
/**
* increase the NodeSet capacity by a factor of its initial size
**/
void NodeSet::increaseSize() {
bufferSize += bufferSize;
Node** tmpNodes = elements;
elements = new Node*[bufferSize];
int i=0;
for (i=0;i < elementCount; i++) elements[i] = tmpNodes[i];
for (;i<bufferSize;i++)elements[i] = 0;
delete [] tmpNodes;
} //-- increaseSize
/**
* Shifts all elements at the specified index to down by 1
**/
void NodeSet::shiftDown(int index) {
if ((index <= 0) || (index > elementCount)) return;
//-- from Java
//-- System.arraycopy(elements, index, elements, index - 1, elementCount - index);
for (int i = index; i < elementCount; i++) {
elements[i-1] = elements[i];
}
elements[elementCount-1] = 0;
} //-- shiftDown
/**
* Shifts all elements at the specified index up by 1
**/
void NodeSet::shiftUp(int index) {
if (index == elementCount) return;
if (elementCount == bufferSize) increaseSize();
//-- from Java
//-- System.arraycopy(elements, index, elements, index + 1, elementCount - index);
for (int i = elementCount; i > index; i--) {
elements[i] = elements[i-1];
}
} //-- shiftUp
//------------------------------------/
//- Virtual Methods from: ExprResult -/
//------------------------------------/
/**
* Returns the type of ExprResult represented
* @return the type of ExprResult represented
**/
short NodeSet::getResultType() {
return ExprResult::NODESET;
} //-- getResultType
/**
* Converts this ExprResult to a Boolean (MBool) value
* @return the Boolean value
**/
MBool NodeSet::booleanValue() {
return (MBool) (size() > 0);
} //- booleanValue
/**
* Converts this ExprResult to a Number (double) value
* @return the Number value
**/
double NodeSet::numberValue() {
// OG+
// As per the XPath spec, the number value of a node-set is the number value
// of its string value.
String str;
stringValue(str);
Double dbl(str);
return dbl.doubleValue();
// OG-
} //-- numberValue
/**
* Creates a String representation of this ExprResult
* @param str the destination string to append the String representation to.
**/
void NodeSet::stringValue(String& str) {
if ( size()>0) {
XMLDOMUtils::getNodeValue(get(0), &str);
}
} //-- stringValue

View File

@@ -0,0 +1,241 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* Larry Fitzpatrick, OpenText, lef@opentext.com
* -- moved initialization of DEFAULT_SIZE to NodeSet.cpp
*
* $Id: NodeSet.h,v 1.1 2000-04-06 07:45:33 kvisco%ziplink.net Exp $
*/
/**
* NodeSet
* @author <a href="mailto:kvisco@ziplink.net">Keith Visco</a>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:33 $
**/
#ifndef TRANSFRMX_NODESET_H
#define TRANSFRMX_NODESET_H
#include "MITREObject.h"
#include "dom.h"
#include "ExprResult.h"
#include "XMLDOMUtils.h"
class NodeSet : public ExprResult {
public:
//----------------/
//- Constructors -/
//----------------/
/**
* Creates a new NodeSet with the default Size
**/
NodeSet();
/**
* Creates a new NodeSet with the specified Size
**/
NodeSet(int size);
/**
* Creates a new NodeSet using the given NodeSet
**/
NodeSet(const NodeSet& source);
/**
* Destructor for NodeSet, will not delete Node References
**/
virtual ~NodeSet();
/**
* Adds the specified Node to this NodeSet if it is not already
* contained within in this NodeSet.
* @param node the Node to add to the NodeSet
* @return true if the Node is added to the NodeSet
**/
MBool add(Node* node);
/**
* Adds the specified Node to the NodeSet at the specified index,
* as long as the Node is not already contained within the set
* @param node the Node to add to the NodeSet
* @return true if the Node is added to the NodeSet
* @exception IndexOutOfBoundsException
**/
MBool add(int index, Node* node);
/**
* Removes all elements from the list
**/
void clear();
/**
* Returns true if the specified Node is contained in the set.
* if the specfied Node is null, then if the NodeSet contains a null
* value, true will be returned.
* @param node the element to search the NodeSet for
* @return true if specified Node is contained in the NodeSet
**/
MBool contains(Node* node);
/**
* Copies the elements of this NodeSet, into the destination NodeSet
**/
void copyInto(NodeSet& dest) const;
/**
* Compares the specified object with this NodeSet for equality.
* Returns true if and only if the specified Object is a NodeSet
* that is the same size as this NodeSet and all of its associated
* Nodes are contained within this NodeSet.
* @return true if and only if the specified Object is a NodeSet
* that is the same size as this NodeSet and all of its associated
* Nodes are contained within this NodeSet.
**/
MBool equals(NodeSet* nodeSet);
/**
* Returns the Node at the specified position in this NodeSet.
* @param index the position of the Node to return
* @exception IndexOutOfBoundsException
**/
Node* get(int index);
/**
* Returns the index of the specified Node,
* or -1 if the Node is not contained in the NodeSet
* @param node the Node to get the index for
**/
int indexOf(Node* node);
/**
* Returns true if there are no Nodes in the NodeSet.
* @return true if there are no Nodes in the NodeSet.
**/
MBool isEmpty();
/**
* Removes the Node at the specified index from the NodeSet
* @param index the position in the NodeSet to remove the Node from
* @return the Node that was removed from the list
**/
Node* remove(int index);
/**
* Removes the the specified Node from the NodeSet
* @param node the Node to remove from the NodeSet
* @return true if the Node was removed from the list
**/
MBool remove(Node* node);
/**
* Returns the number of elements in the NodeSet
* @return the number of elements in the NodeSet
**/
int size() const;
/**
* Creates a String representation of this NodeSet
* @param str the destination string to append the String representation to.
**/
void toString(String& str);
//------------------------------------/
//- Virtual Methods from: ExprResult -/
//------------------------------------/
/**
* Returns the type of ExprResult represented
* @return the type of ExprResult represented
**/
virtual short getResultType();
/**
* Converts this ExprResult to a Boolean (MBool) value
* @return the Boolean value
**/
virtual MBool booleanValue();
/**
* Converts this ExprResult to a Number (double) value
* @return the Number value
**/
virtual double numberValue();
/**
* Creates a String representation of this ExprResult
* @param str the destination string to append the String representation to.
**/
virtual void stringValue(String& str);
private:
//-------------------/
//- Private Members -/
//-------------------/
static const int DEFAULT_SIZE;
Node** elements;
int initialSize;
int bufferSize;
/**
* The next available location in the elements array
**/
int elementCount;
//-------------------/
//- Private Methods -/
//-------------------/
/**
* Helper method for constructors
**/
void initialize(int size);
/**
* increase the NodeSet capacity by a factor of its initial size
**/
void increaseSize();
/**
* Shifts all elements at the specified index to down by 1
**/
void shiftDown(int index);
/**
* Shifts all elements at the specified index up by 1
**/
void shiftUp(int index);
}; //-- NodeSet
#endif

View File

@@ -0,0 +1,166 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: NodeSetFunctionCall.cpp,v 1.1 2000-04-06 07:45:34 kvisco%ziplink.net Exp $
*/
/**
* NodeSetFunctionCall
* A representation of the XPath NodeSet funtions
* @author <A HREF="mailto:kvisco@ziplink.net">Keith Visco</a>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:34 $
**/
#include "FunctionLib.h"
/**
* Creates a default NodeSetFunctionCall. The Position function
* is the default
**/
NodeSetFunctionCall::NodeSetFunctionCall() : FunctionCall(XPathNames::POSITION_FN) {
type = POSITION;
} //-- NodeSetFunctionCall
/**
* Creates a NodeSetFunctionCall of the given type
**/
NodeSetFunctionCall::NodeSetFunctionCall(short type) : FunctionCall() {
this->type = type;
switch ( type ) {
case COUNT :
FunctionCall::setName(XPathNames::COUNT_FN);
break;
case LAST :
FunctionCall::setName(XPathNames::LAST_FN);
break;
case LOCAL_NAME:
FunctionCall::setName(XPathNames::LOCAL_NAME_FN);
break;
case NAME:
FunctionCall::setName(XPathNames::NAME_FN);
break;
case NAMESPACE_URI:
FunctionCall::setName(XPathNames::NAMESPACE_URI_FN);
break;
default:
FunctionCall::setName(XPathNames::POSITION_FN);
break;
}
} //-- NodeSetFunctionCall
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* NodeSetFunctionCall::evaluate(Node* context, ContextState* cs) {
NodeSet* nodeSet = (NodeSet*)cs->getNodeSetStack()->peek();
ListIterator* iter = params.iterator();
Int32 argc = params.getLength();
ExprResult* result = 0;
Expr* param = 0;
switch ( type ) {
case COUNT :
if ( argc == 1 ) {
double count = 0.0;
param = (Expr*)iter->next();
ExprResult* exprResult = param->evaluate(context, cs);
if ( exprResult->getResultType() != ExprResult::NODESET ) {
String err("NodeSet expected as argument to count()");
cs->recieveError(err);
}
else count = (double) ((NodeSet*)exprResult)->size();
delete exprResult;
result = new NumberResult(count);
}
else {
String err(INVALID_PARAM_COUNT);
this->toString(err);
cs->recieveError(err);
result = new NumberResult(0.0);
}
break;
case LAST :
if ( nodeSet ) result = new NumberResult((double)nodeSet->size());
else result = new NumberResult(0.0);
break;
case LOCAL_NAME:
case NAME:
case NAMESPACE_URI :
{
String name;
Node* node = 0;
if ( argc < 2 ) {
//-- check for optional arg
if ( argc == 1) {
param = (Expr*)iter->next();
ExprResult* exprResult = param->evaluate(context, cs);
if ( exprResult->getResultType() != ExprResult::NODESET ) {
String err("NodeSet expected as argument to ");
this->toString(err);
cs->recieveError(err);
}
else {
NodeSet* nodes = (NodeSet*)exprResult;
if (nodes->size() > 0) node = nodes->get(0);
}
delete exprResult;
}
if ( !node ) node = context;
switch ( type ) {
case LOCAL_NAME :
XMLUtils::getLocalPart(node->getNodeName(),name);
break;
case NAMESPACE_URI :
XMLUtils::getNameSpace(node->getNodeName(),name);
break;
default:
name = node->getNodeName();
break;
}
result = new StringResult(name);
}
else {
String err(INVALID_PARAM_COUNT);
this->toString(err);
cs->recieveError(err);
result = new StringResult("");
}
break;
}
default : //-- position
if ( nodeSet )
result = new NumberResult((double)nodeSet->indexOf(context)+1);
else
result = new NumberResult(0.0);
break;
}
delete iter;
return result;
} //-- evaluate

View File

@@ -0,0 +1,66 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: NumberExpr.cpp,v 1.1 2000-04-06 07:45:34 kvisco%ziplink.net Exp $
*/
#include "Expr.h"
//--------------/
//- NumberExpr -/
//--------------/
NumberExpr::NumberExpr() {
numberResult.setValue(0.0);
} //-- NumberExpr
NumberExpr::NumberExpr(double dbl) {
numberResult.setValue(dbl);
} //-- NumberExpr
NumberExpr::~NumberExpr() {
} //-- ~NumberExpr
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* NumberExpr::evaluate(Node* context, ContextState* cs) {
return new NumberResult(numberResult);
} //-- evaluate
/**
* Returns the String representation of this Expr.
* @param dest the String to use when creating the String
* representation. The String representation will be appended to
* any data in the destination String, to allow cascading calls to
* other #toString() methods for Expressions.
* @return the String representation of this Expr.
**/
void NumberExpr::toString(String& str) {
numberResult.stringValue(str);
} //-- toString

View File

@@ -0,0 +1,146 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Olivier Gerardin, ogerardin@vo.lu
* -- original author.
*/
/**
* NumberFunctionCall
* A representation of the XPath Number funtions
* @author <A HREF="mailto:ogerardin@vo.lu">Olivier Gerardin</A>
**/
#include "FunctionLib.h"
/**
* Creates a default NumberFunctionCall. The number() function
* is the default
**/
NumberFunctionCall::NumberFunctionCall() : FunctionCall(XPathNames::NUMBER_FN) {
type = NUMBER;
} //-- NumberFunctionCall
/**
* Creates a NumberFunctionCall of the given type
**/
NumberFunctionCall::NumberFunctionCall(short type) : FunctionCall() {
this->type = type;
switch ( type ) {
case ROUND :
FunctionCall::setName(XPathNames::ROUND_FN);
break;
case CEILING :
FunctionCall::setName(XPathNames::CEILING_FN);
break;
case FLOOR :
FunctionCall::setName(XPathNames::FLOOR_FN);
break;
case NUMBER :
default :
FunctionCall::setName(XPathNames::NUMBER_FN);
break;
}
} //-- NumberFunctionCall
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* NumberFunctionCall::evaluate(Node* context, ContextState* cs) {
NumberResult* result = new NumberResult();
ListIterator* iter = params.iterator();
int argc = params.getLength();
Expr* param = 0;
String err;
switch ( type ) {
case CEILING :
if ( requireParams(1, 1, cs) ) {
double dbl = evaluateToNumber((Expr*)iter->next(), context, cs);
result->setValue(ceil(dbl));
}
else {
result->setValue(0.0);
}
break;
case FLOOR :
if ( requireParams(1, 1, cs) ) {
double dbl = evaluateToNumber((Expr*)iter->next(), context, cs);
result->setValue(floor(dbl));
}
else {
result->setValue(0.0);
}
break;
case ROUND :
if ( requireParams(1, 1, cs) ) {
double dbl = evaluateToNumber((Expr*)iter->next(), context, cs);
double res = rint(dbl);
if ((dbl>0.0) && (res == dbl-0.5)) {
// fix for native round function from math library (rint()) which does not
// match the XPath spec for positive half values
result->setValue(res+1.0);
}
else {
result->setValue(res);
}
break;
}
else result->setValue(0.0);
break;
case NUMBER :
default : //-- number( object? )
if ( requireParams(0, 1, cs) ) {
if (iter->hasNext()) {
param = (Expr*) iter->next();
ExprResult* exprResult = param->evaluate(context, cs);
result->setValue(exprResult->numberValue());
delete exprResult;
}
else {
String resultStr;
String temp;
XMLDOMUtils::getNodeValue(context, &temp);
if ( cs->isStripSpaceAllowed(context) ) {
XMLUtils::stripSpace(temp, resultStr);
}
else {
resultStr.append(temp);
}
Double dbl(resultStr);
result->setValue(dbl.doubleValue());
}
}
else {
result = new NumberResult(0.0);
}
break;
}
delete iter;
return result;
} //-- evaluate

View File

@@ -0,0 +1,112 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: NumberResult.cpp,v 1.1 2000-04-06 07:45:35 kvisco%ziplink.net Exp $
*/
/**
* NumberResult
* Represents the a number as the result of evaluating an Expr
* @author <A HREF="mailto:kvisco@ziplink.net">Keith Visco</A>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:35 $
**/
#include "ExprResult.h"
/**
* Default Constructor
**/
NumberResult::NumberResult() {
value = 0.0;
} //-- NumberResult
NumberResult::NumberResult(const NumberResult& nbrResult) {
this->value = nbrResult.getValue();
} //-- NumberResult
/**
* Creates a new NumberResult with the value of the given double parameter
* @param dbl the double to use for initialization of this NumberResult's value
**/
NumberResult::NumberResult(double dbl) {
this->value = dbl;
} //-- NumberResult
/**
* Returns the value of this NumberResult
* @return the value of this NumberResult
**/
double NumberResult::getValue() const {
return this->value;
} //-- getValue
/**
*
**/
MBool NumberResult::isNaN() const {
return Double::isNaN(value);
} //-- isNaN
/**
* Sets the value of this NumberResult
* @param dbl the double to use for this NumberResult's value
**/
void NumberResult::setValue(double dbl) {
this->value = dbl;
} //-- setValue
/**
* Sets the value of this NumberResult
* @param nbrResult the NumberResult to use for setting this NumberResult's value
**/
void NumberResult::setValue(const NumberResult& nbrResult) {
this->value = nbrResult.getValue();
} //-- setValue
/*
* Virtual Methods from ExprResult
*/
short NumberResult::getResultType() {
return ExprResult::NUMBER;
} //-- getResultType
void NumberResult::stringValue(String& str) {
int intVal = (int)value;
if (intVal == value) { //-- no fraction
Integer::toString(intVal, str);
}
else Double::toString(value, str);
} //-- stringValue
MBool NumberResult::booleanValue() {
// OG+
// As per the XPath spec, the boolean value of a number is true if and only if
// it is neither positive 0 nor negative 0 nor NaN
return (MBool)(this->value != 0.0 && this->value != -0.0 && ! isNaN());
// OG-
} //-- booleanValue
double NumberResult::numberValue() {
return this->value;
} //-- numberValue

View File

@@ -0,0 +1,59 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: ParentExpr.cpp,v 1.1 2000-04-06 07:45:35 kvisco%ziplink.net Exp $
*/
/**
* @author <A HREF="mailto:kvisco@ziplink.net">Keith Visco</A>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:35 $
**/
#include "Expr.h"
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* ParentExpr::evaluate(Node* context, ContextState* cs) {
NodeSet* nodeSet = new NodeSet();
if ( !context ) return nodeSet;
Node* node = context->getParentNode();
if (node) nodeSet->add(node);
return nodeSet;
} //-- evaluate
/**
* Returns the String representation of this NodeExpr.
* @param dest the String to use when creating the String
* representation. The String representation will be appended to
* any data in the destination String, to allow cascading calls to
* other #toString() methods for Expressions.
* @return the String representation of this NodeExpr.
**/
void ParentExpr::toString(String& dest) {
dest.append("..");
} //-- toString

View File

@@ -0,0 +1,185 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: Parser.cpp,v 1.1 2000-04-06 07:45:36 kvisco%ziplink.net Exp $
*/
/**
* Test App for Expressions
* @author <A HREF="mailto:kvisco@ziplink.net">Keith Visco</A>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:36 $
**/
#include <iostream.h>
#include "String.h"
#include "Expr.h"
#include "ExprLexer.h"
#include "ExprParser.h"
#include "NamedMap.h"
#include "ExprResult.h"
void main(int argc, char** argv) {
cout <<endl;
//String pattern("element[position()=1]");
//String pattern("*[text()='foo']");
//String pattern("@*|node()");
String pattern("FSContext/UserList/User[@id=/FSContext/SessionData/@userref]/@priv = 'admin'");
cout <<"Lexically Analyzing: "<<pattern<<endl;
cout<<endl;
ExprLexer lexer(pattern);
Token* token = 0;
int tokenCount = lexer.countAllTokens();
for (int i = 0; i < tokenCount; i++) {
token = lexer.nextToken();
cout <<"Token: ";
if (token) {
cout << token->value;
//-- do padding
for ( int i = token->value.length(); i < 20; i++) cout<<" ";
//-- print token type
switch (token->type) {
case Token::AT_SIGN:
cout << "#AT_SIGN";
break;
case Token::PARENT_OP :
cout<<"#PARENT_OP";
break;
case Token::ANCESTOR_OP :
cout<<"#ANCESTOR_OP";
break;
case Token::L_PAREN :
cout<<"#L_PAREN";
break;
case Token::R_PAREN :
cout<<"#R_PAREN";
break;
case Token::L_BRACKET:
cout<<"#L_BRACKET";
break;
case Token::R_BRACKET:
cout<<"#R_BRACKET";
break;
case Token::COMMA:
cout<<"#COMMA";
break;
case Token::LITERAL:
cout<<"#LITERAL";
break;
case Token::CNAME:
cout<<"#CNAME";
break;
case Token::COMMENT:
cout<<"#COMMENT";
break;
case Token::NODE:
cout<<"#NODE";
break;
case Token::PI:
cout<<"#PI";
break;
case Token::TEXT:
cout<<"#TEXT";
break;
case Token::FUNCTION_NAME:
cout<<"#FUNCTION_NAME";
break;
case Token::WILD_CARD:
cout << "#WILDCARD";
break;
case Token::NUMBER:
cout << "#NUMBER";
break;
case Token::PARENT_NODE :
cout << "#PARENT_NODE";
break;
case Token::SELF_NODE :
cout << "#SELF_NODE";
break;
case Token::VAR_REFERENCE:
cout << "#VAR_REFERENCE";
case Token::AXIS_IDENTIFIER:
cout << "#AXIS_IDENTIFIER";
break;
default:
if ( lexer.isOperatorToken(token) ) {
cout << "#operator";
}
else cout<<"#unknown";
break;
}
}
else cout<<"NULL";
cout<<endl;
}
cout <<endl;
cout <<"Creating Expr: "<<pattern<<endl;
cout<<endl;
ExprParser parser;
Expr* expr = (Expr*)parser.createExpr(pattern);
cout << "Checking result"<<endl;
String resultString;
if ( !expr ) {
cout << "#error, "<<pattern<< " is not valid."<<endl;
}
else {
expr->toString(resultString);
cout << "result: "<<resultString <<endl;
}
NumberExpr numberExpr( -24.0 );
resultString.clear();
numberExpr.toString(resultString);
cout << "NumberExpr: " << resultString << endl << endl;
StringResult strResult("-24");
cout << "StringResult: " << strResult.numberValue() << endl;
//-- AttributeValueTemplate test
String avt("this is a {text()} of {{{{attr value templates}}}}");
expr = parser.createAttributeValueTemplate(avt);
resultString.clear();
expr->toString(resultString);
cout << "result of avt: "<<resultString <<endl;
//-- clean up
delete expr;
} //-- main

View File

@@ -0,0 +1,306 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
* Bob Miller, kbob@oblix.com
* -- plugged core leak.
*
* $Id: PathExpr.cpp,v 1.1 2000-04-06 07:45:36 kvisco%ziplink.net Exp $
*/
#include "Expr.h"
//------------/
//- PathExpr -/
//------------/
/**
* Creates a new PathExpr
**/
PathExpr::PathExpr() {
//-- do nothing
}
/**
* Destructor, will delete all Pattern Expressions
**/
PathExpr::~PathExpr() {
ListIterator* iter = expressions.iterator();
while ( iter->hasNext() ) {
iter->next();
PathExprItem* pxi = (PathExprItem*)iter->remove();
delete pxi->pExpr;
delete pxi;
}
delete iter;
} //-- ~PathExpr
/**
* Adds the PatternExpr to this PathExpr
* @param expr the Expr to add to this PathExpr
* @param index the index at which to add the given Expr
**/
void PathExpr::addPatternExpr(int index, PatternExpr* expr, short ancestryOp) {
if (expr) {
PathExprItem* pxi = new PathExprItem;
pxi->pExpr = expr;
pxi->ancestryOp = ancestryOp;
expressions.insert(index, pxi);
}
} //-- addPattenExpr
/**
* Adds the PatternExpr to this PathExpr
* @param expr the Expr to add to this PathExpr
**/
void PathExpr::addPatternExpr(PatternExpr* expr, short ancestryOp) {
if (expr) {
PathExprItem* pxi = new PathExprItem;
pxi->pExpr = expr;
pxi->ancestryOp = ancestryOp;
expressions.add(pxi);
}
} //-- addPattenExpr
MBool PathExpr::isAbsolute() {
if ( expressions.getLength() > 0 ) {
ListIterator* iter = expressions.iterator();
PathExprItem* pxi = (PathExprItem*)iter->next();
delete iter;
return (pxi->ancestryOp != RELATIVE_OP);
}
return MB_FALSE;
} //-- isAbsolute
//------------------------------------/
//- Virtual methods from PatternExpr -/
//------------------------------------/
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* PathExpr::evaluate(Node* context, ContextState* cs) {
//-- add selectExpr functionality here
if ( (!context) || (expressions.getLength() == 0))
return new NodeSet(0);
NodeSet* nodes = new NodeSet();
if ((isAbsolute()) && (context->getNodeType() != Node::DOCUMENT_NODE))
nodes->add(context->getOwnerDocument());
else
nodes->add(context);
ListIterator* iter = expressions.iterator();
MBool ancestorMode = MB_FALSE;
while ( iter->hasNext() ) {
PathExprItem* pxi = (PathExprItem*)iter->next();
ancestorMode = (ancestorMode || (pxi->ancestryOp == ANCESTOR_OP));
NodeSet* tmpNodes = 0;
cs->getNodeSetStack()->push(nodes);
for (int i = 0; i < nodes->size(); i++) {
Node* node = nodes->get(i);
#if 0
NodeSet* xNodes = (NodeSet*) pxi->pExpr->evaluate(node, cs);
#else
ExprResult *res = pxi->pExpr->evaluate(node, cs);
if (!res || res->getResultType() != ExprResult::NODESET)
continue;
NodeSet* xNodes = (NodeSet *) res;
#endif
if ( tmpNodes ) {
xNodes->copyInto(*tmpNodes);
}
else {
tmpNodes = xNodes;
xNodes = 0;
}
delete xNodes;
//-- handle ancestorMode
if ( ancestorMode ) fromDescendants(pxi->pExpr, node, cs, tmpNodes);
}
delete (NodeSet*) cs->getNodeSetStack()->pop();
nodes = tmpNodes;
if ( nodes->size() == 0 ) break;
}
delete iter;
return nodes;
} //-- evaluate
/**
* Selects from the descendants of the context node
* all nodes that match the PatternExpr
* -- this will be moving to a Utility class
**/
void PathExpr::fromDescendants
(PatternExpr* pExpr, Node* context, ContextState* cs, NodeSet* nodes)
{
if (( !context ) || (! pExpr )) return;
NodeList* nl = context->getChildNodes();
for (int i = 0; i < nl->getLength(); i++) {
Node* child = nl->item(i);
if (pExpr->matches(child, context, cs))
nodes->add(child);
//-- check childs descendants
if (child->hasChildNodes())
fromDescendants(pExpr, child, cs, nodes);
}
} //-- fromDescendants
/**
* Returns the default priority of this Pattern based on the given Node,
* context Node, and ContextState.
* If this pattern does not match the given Node under the current context Node and
* ContextState then Negative Infinity is returned.
**/
double PathExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
if ( matches(node, context, cs) ) {
int size = expressions.getLength();
if ( size == 1) {
ListIterator* iter = expressions.iterator();
PathExprItem* pxi = (PathExprItem*)iter->next();
delete iter;
return pxi->pExpr->getDefaultPriority(node, context, cs);
}
else if ( size > 1 ) {
return 0.5;
}
}
return Double::NEGATIVE_INFINITY;
} //-- getDefaultPriority
/**
* Determines whether this PatternExpr matches the given node within
* the given context
**/
MBool PathExpr::matches(Node* node, Node* context, ContextState* cs) {
if ( (!node) || (expressions.getLength() == 0))
return MB_FALSE;
NodeSet nodes;
nodes.add(node);
ListIterator* iter = expressions.iterator();
iter->reverse();
NodeSet tmpNodes;
MBool result = MB_FALSE;
while ( iter->hasNext() ) {
PathExprItem* pxi = (PathExprItem*)iter->next();
for (int i = 0; i < nodes.size(); i++) {
Node* tnode = nodes.get(i);
//-- select node's parent or ancestors
switch (pxi->ancestryOp) {
case ANCESTOR_OP:
{
Node* parent = tnode;
while (parent = cs->getParentNode(parent)) {
if (pxi->pExpr->matches(tnode, parent, cs))
tmpNodes.add(parent);
}
break;
}
case PARENT_OP:
{
Node* parent = cs->getParentNode(tnode);
if (parent) {
if (pxi->pExpr->matches(tnode, parent, cs))
tmpNodes.add(parent);
}
break;
}
default:
if ( !iter->hasNext() ) {
result = pxi->pExpr->matches(tnode, context, cs);
}
else {
//-- error in expression
tmpNodes.clear();
nodes.clear();
delete iter;
return MB_FALSE;
}
break;
}
} //-- for
nodes.clear();
tmpNodes.copyInto(nodes);
tmpNodes.clear();
}
delete iter;
if ( this->isAbsolute()) {
Node* doc = node->getOwnerDocument();
return (MBool) nodes.contains(doc);
}
return (MBool) (result || (nodes.size() > 0));
} //-- matches
/**
* Returns the String representation of this PatternExpr.
* @param dest the String to use when creating the String
* representation. The String representation will be appended to
* any data in the destination String, to allow cascading calls to
* other #toString() methods for Expressions.
* @return the String representation of this PatternExpr.
**/
void PathExpr::toString(String& dest) {
ListIterator* iter = expressions.iterator();
while ( iter->hasNext() ) {
//-- set operator
PathExprItem* pxi = (PathExprItem*)iter->next();
switch ( pxi->ancestryOp ) {
case ANCESTOR_OP:
dest.append("//");
break;
case PARENT_OP:
dest.append('/');
break;
default:
break;
}
pxi->pExpr->toString(dest);
}
delete iter;
} //-- toString

View File

@@ -0,0 +1,143 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: PredicateList.cpp,v 1.1 2000-04-06 07:45:37 kvisco%ziplink.net Exp $
*/
#include "Expr.h"
/**
* Represents an ordered list of Predicates,
* for use with Step and Filter Expressions
* @author <A HREF="mailto:kvisco@ziplink.net">Keith Visco</A>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:37 $
**/
//-- PredicateList Implementation --/
PredicateList::PredicateList() {
} //-- PredicateList
/**
* Destructor, will delete all Expressions in the list, so remove
* any you may need
**/
PredicateList::~PredicateList() {
//cout << "-PredicateList() - start"<<endl;
ListIterator* iter = predicates.iterator();
while ( iter->hasNext() ) {
iter->next();
Expr* expr = (Expr*) iter->remove();
delete expr;
}
delete iter;
//cout << "~PredicateList() - end"<<endl;
} //-- ~PredicateList
/**
* Adds the given Expr to the list
* @param expr the Expr to add to the list
**/
void PredicateList::add(Expr* expr) {
predicates.add(expr);
} //-- add
void PredicateList::evaluatePredicates(NodeSet* nodes, ContextState* cs) {
if ( !nodes ) return;
ListIterator* iter = predicates.iterator();
NodeSet remNodes(nodes->size());
Stack* nsStack = cs->getNodeSetStack();
nsStack->push(nodes);
while ( iter->hasNext() ) {
int nIdx = 0;
Expr* expr = (Expr*) iter->next();
//-- filter each node currently in the NodeSet
for (nIdx = 0; nIdx < nodes->size(); nIdx++) {
Node* node = nodes->get(nIdx);
//-- if expr evaluates to true using the node as it's context,
//-- then we can keep it, otherwise add to remove list
ExprResult* exprResult = expr->evaluate(node,cs);
if ( !exprResult ) {
cout << "ExprResult == null" << endl;
}
else {
switch(exprResult->getResultType()) {
case ExprResult::NUMBER :
{
//-- handle default position()
int position = nodes->indexOf(node)+1;
if (( position <= 0 ) ||
( ((double)position) != exprResult->numberValue()))
remNodes.add(node);
break;
}
default:
if (! exprResult->booleanValue() ) remNodes.add(node);
break;
}
}
}
//-- remove unmatched nodes
for (nIdx = 0; nIdx < remNodes.size(); nIdx++)
nodes->remove(remNodes.get(nIdx));
//-- clear remove list
remNodes.clear();
}
nsStack->pop();
delete iter;
} //-- evaluatePredicates
/**
* returns true if this predicate list is empty
**/
MBool PredicateList::isEmpty() {
return (MBool)(predicates.getLength() == 0);
} //-- isEmpty
/**
* Removes the given Expr from the list
* @param expr the Expr to remove from the list
**/
Expr* PredicateList::remove(Expr* expr) {
return (Expr*)predicates.remove(expr);
} //-- remove
void PredicateList::toString(String& dest) {
ListIterator* iter = predicates.iterator();
while ( iter->hasNext() ) {
Expr* expr = (Expr*) iter->next();
dest.append("[");
expr->toString(dest);
dest.append("]");
}
delete iter;
} //-- toString

View File

@@ -0,0 +1,208 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: RelationalExpr.cpp,v 1.1 2000-04-06 07:45:38 kvisco%ziplink.net Exp $
*/
#include "Expr.h"
//------------------/
//- RelationalExpr -/
//------------------/
RelationalExpr::RelationalExpr() {
this->op = EQUAL;
this->leftExpr = 0;
this->rightExpr = 0;
} //-- RelationalExpr
RelationalExpr::RelationalExpr(Expr* leftExpr, Expr* rightExpr, short op) {
this->op = op;
this->leftExpr = leftExpr;
this->rightExpr = rightExpr;
} //-- RelationalExpr
RelationalExpr::~RelationalExpr() {
delete leftExpr;
delete rightExpr;
} //-- ~RelationalExpr
/**
* Compares the two ExprResults based on XPath 1.0 Recommendation (section 3.4)
**/
MBool RelationalExpr::compareResults(ExprResult* left, ExprResult* right) {
short ltype = left->getResultType();
short rtype = right->getResultType();
MBool result = MB_FALSE;
//-- handle case for just Left NodeSet or Both NodeSets
if (ltype == ExprResult::NODESET) {
NodeSet* nodeSet = (NodeSet*)left;
for ( int i = 0; i < nodeSet->size(); i++) {
String str;
Node* node = nodeSet->get(i);
XMLDOMUtils::getNodeValue(node, &str);
StringResult strResult(str);
result = compareResults(&strResult, right);
if ( result ) break;
}
}
//-- handle case for Just Right NodeSet
else if ( rtype == ExprResult::NODESET) {
NodeSet* nodeSet = (NodeSet*)right;
for ( int i = 0; i < nodeSet->size(); i++) {
String str;
Node* node = nodeSet->get(i);
XMLDOMUtils::getNodeValue(node, &str);
StringResult strResult(str);
result = compareResults(left, &strResult);
if ( result ) break;
}
}
//-- neither NodeSet
else {
if ( op == NOT_EQUAL) {
if ((ltype == ExprResult::BOOLEAN)
|| (rtype == ExprResult::BOOLEAN)) {
result = (left->booleanValue() != right->booleanValue());
}
else if ((ltype == ExprResult::NUMBER) ||
(rtype == ExprResult::NUMBER)) {
result = (left->numberValue() != right->numberValue());
}
else {
String lStr;
left->stringValue(lStr);
String rStr;
right->stringValue(rStr);
result = !lStr.isEqual(rStr);
}
}
else if ( op == EQUAL) {
if ((ltype == ExprResult::BOOLEAN)
|| (rtype == ExprResult::BOOLEAN)) {
result = (left->booleanValue() == right->booleanValue());
}
else if ((ltype == ExprResult::NUMBER) ||
(rtype == ExprResult::NUMBER)) {
result = (left->numberValue() == right->numberValue());
}
else {
String lStr;
left->stringValue(lStr);
String rStr;
right->stringValue(rStr);
result = lStr.isEqual(rStr);
}
}
else {
double leftDbl = left->numberValue();
double rightDbl = right->numberValue();
switch( op ) {
case LESS_THAN:
result = (MBool) (leftDbl < rightDbl);
break;
case LESS_OR_EQUAL:
result = (MBool) (leftDbl <= rightDbl);
break;
case GREATER_THAN :
result = (MBool) (leftDbl > rightDbl);
break;
case GREATER_OR_EQUAL:
result = (MBool) (leftDbl >= rightDbl);
break;
}
}
}
return result;
} //-- compareResult
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* RelationalExpr::evaluate(Node* context, ContextState* cs) {
//-- get result of left expression
ExprResult* lResult = 0;
if ( leftExpr ) lResult = leftExpr->evaluate(context, cs);
else return new BooleanResult();
//-- get result of right expr
ExprResult* rResult = 0;
if ( rightExpr ) rResult = rightExpr->evaluate(context, cs);
else {
delete lResult;
return new BooleanResult();
}
return new BooleanResult(compareResults(lResult, rResult));
} //-- evaluate
/**
* Returns the String representation of this Expr.
* @param dest the String to use when creating the String
* representation. The String representation will be appended to
* any data in the destination String, to allow cascading calls to
* other #toString() methods for Expressions.
* @return the String representation of this Expr.
**/
void RelationalExpr::toString(String& str) {
if ( leftExpr ) leftExpr->toString(str);
else str.append("null");
switch ( op ) {
case NOT_EQUAL:
str.append("!=");
break;
case LESS_THAN:
str.append("<");
break;
case LESS_OR_EQUAL:
str.append("<=");
break;
case GREATER_THAN :
str.append(">");
break;
case GREATER_OR_EQUAL:
str.append(">=");
break;
default:
str.append("=");
break;
}
if ( rightExpr ) rightExpr->toString(str);
else str.append("null");
} //-- toString

View File

@@ -0,0 +1,82 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: RootExpr.cpp,v 1.1 2000-04-06 07:45:39 kvisco%ziplink.net Exp $
*/
#include "Expr.h"
MBool RootExpr::isAbsolute() {
return MB_TRUE;
} //-- isAbsolute
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* RootExpr::evaluate(Node* context, ContextState* cs) {
NodeSet* nodeSet = new NodeSet();
if ( !context ) return nodeSet;
nodeSet->add(context->getOwnerDocument());
return nodeSet;
} //-- evaluate
/**
* Returns the default priority of this Pattern based on the given Node,
* context Node, and ContextState.
* If this pattern does not match the given Node under the current context Node and
* ContextState then Negative Infinity is returned.
**/
double RootExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
if ( matches(node, context, cs) ) {
return 0.5;
}
else return Double::NEGATIVE_INFINITY;
} //-- getDefaultPriority
/**
* Determines whether this NodeExpr matches the given node within
* the given context
**/
MBool RootExpr::matches(Node* node, Node* context, ContextState* cs) {
if ( node ) {
return (MBool) (node->getNodeType() == Node::DOCUMENT_NODE);
}
return MB_FALSE;
} //-- matches
/**
* Returns the String representation of this PatternExpr.
* @param dest the String to use when creating the String
* representation. The String representation will be appended to
* any data in the destination String, to allow cascading calls to
* other #toString() methods for Expressions.
* @return the String representation of this PatternExpr.
**/
void RootExpr::toString(String& dest) {
dest.append('/');
} //-- toString

View File

@@ -0,0 +1,79 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: StringExpr.cpp,v 1.1 2000-04-06 07:45:39 kvisco%ziplink.net Exp $
*/
#include "Expr.h"
/**
* StringExpr
* @author <A HREF="mailto:kvisco@ziplink.net">Keith Visco</A>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:39 $
**/
/**
* Creates a new StringExpr
**/
StringExpr::StringExpr() {};
StringExpr::StringExpr(String& value) {
//-- copy value
this->value = value;
} //-- StringExpr
StringExpr::StringExpr(const String& value) {
//-- copy value
this->value.append(value);
} //-- StringExpr
/**
* Default Destructor
**/
StringExpr::~StringExpr() {};
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* StringExpr::evaluate(Node* context, ContextState* cs) {
return new StringResult(value);
} //-- evaluate
/**
* Returns the String representation of this Expr.
* @param dest the String to use when creating the String
* representation. The String representation will be appended to
* any data in the destination String, to allow cascading calls to
* other #toString() methods for Expressions.
* @return the String representation of this Expr.
**/
void StringExpr::toString(String& str) {
str.append('\'');
str.append(value);
str.append('\'');
} //-- toString

View File

@@ -0,0 +1,243 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: StringFunctionCall.cpp,v 1.1 2000-04-06 07:45:41 kvisco%ziplink.net Exp $
*/
/**
* StringFunctionCall
* A representation of the XPath String funtions
* @author <A HREF="mailto:kvisco@ziplink.net">Keith Visco</A>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:41 $
**/
#include "FunctionLib.h"
/**
* Creates a default StringFunctionCall. The string() function
* is the default
**/
StringFunctionCall::StringFunctionCall() : FunctionCall(XPathNames::STRING_FN) {
type = STRING;
} //-- StringFunctionCall
/**
* Creates a StringFunctionCall of the given type
**/
StringFunctionCall::StringFunctionCall(short type) : FunctionCall() {
this->type = type;
switch ( type ) {
case CONCAT:
FunctionCall::setName(XPathNames::CONCAT_FN);
break;
case CONTAINS:
FunctionCall::setName(XPathNames::CONTAINS_FN);
break;
case STARTS_WITH:
FunctionCall::setName(XPathNames::STARTS_WITH_FN);
break;
case STRING_LENGTH:
FunctionCall::setName(XPathNames::STRING_LENGTH_FN);
break;
case SUBSTRING:
FunctionCall::setName(XPathNames::SUBSTRING_FN);
break;
case SUBSTRING_AFTER:
FunctionCall::setName(XPathNames::SUBSTRING_AFTER_FN);
break;
case SUBSTRING_BEFORE:
FunctionCall::setName(XPathNames::SUBSTRING_BEFORE_FN);
break;
case TRANSLATE:
FunctionCall::setName(XPathNames::TRANSLATE_FN);
break;
default:
FunctionCall::setName(XPathNames::STRING_FN);
break;
}
} //-- StringFunctionCall
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* StringFunctionCall::evaluate(Node* context, ContextState* cs) {
ListIterator* iter = params.iterator();
Int32 argc = params.getLength();
String err;
ExprResult* result = 0;
switch ( type ) {
case CONCAT :
if ( requireParams(2, cs) ) {
String resultStr;
while(iter->hasNext()) {
evaluateToString((Expr*)iter->next(),context, cs, resultStr);
}
result = new StringResult(resultStr);
}
else result = new StringResult("");
break;
case CONTAINS :
if ( requireParams(2, 2, cs) ) {
String arg1, arg2;
evaluateToString((Expr*)iter->next(),context, cs, arg1);
evaluateToString((Expr*)iter->next(),context, cs, arg2);
result = new BooleanResult((MBool)(arg1.indexOf(arg2) >= 0));
}
else result = new BooleanResult(MB_FALSE);
break;
case STARTS_WITH :
if ( requireParams(2, 2, cs) ) {
String arg1, arg2;
evaluateToString((Expr*)iter->next(),context, cs, arg1);
evaluateToString((Expr*)iter->next(),context, cs, arg2);
result = new BooleanResult((MBool)(arg1.indexOf(arg2) == 0));
}
else result = new BooleanResult(MB_FALSE);
break;
case STRING_LENGTH:
if ( requireParams(0, 1, cs) ) {
String resultStr;
if ( argc == 1) {
evaluateToString((Expr*)iter->next(),context, cs, resultStr);
}
else XMLDOMUtils::getNodeValue(context, &resultStr);
result = new NumberResult( (double) resultStr.length());
}
else result = new NumberResult(0.0);
break;
case SUBSTRING:
if ( requireParams(2, 3, cs) ) {
String src;
evaluateToString((Expr*)iter->next(),context, cs, src);
double dbl = evaluateToNumber((Expr*)iter->next(), context, cs);
//-- check for NaN
if ( Double::isNaN(dbl)) {
result = new StringResult("");
break;
}
Int32 startIdx = (Int32)ceil(dbl);
Int32 endIdx = src.length();
if ( argc == 3) {
dbl += evaluateToNumber((Expr*)iter->next(),context, cs);
if (dbl == Double::POSITIVE_INFINITY) endIdx++;
else if ( dbl == Double::NEGATIVE_INFINITY ) endIdx = 0;
else endIdx = (Int32)floor(dbl);
}
String resultStr;
//-- strings are indexed starting at 1 for XSL
//-- adjust to a 0-based index
if (startIdx > 0) startIdx--;
else if (startIdx == 0 ) endIdx--;
else startIdx=0;
src.subString(startIdx,endIdx,resultStr);
result = new StringResult(resultStr);
}
else result = new StringResult("");
break;
case SUBSTRING_AFTER:
if ( requireParams(2, 2, cs) ) {
String arg1, arg2;
evaluateToString((Expr*)iter->next(),context, cs, arg1);
evaluateToString((Expr*)iter->next(),context, cs, arg2);
Int32 idx = arg1.indexOf(arg2);
if ((idx >= 0)&&(idx<arg1.length())) {
Int32 len = arg2.length();
arg2.clear();
arg1.subString(idx+len,arg2);
result = new StringResult(arg2);
break;
}
}
result = new StringResult("");
break;
case SUBSTRING_BEFORE:
if ( requireParams(2, 2, cs) ) {
String arg1, arg2;
evaluateToString((Expr*)iter->next(),context, cs, arg1);
evaluateToString((Expr*)iter->next(),context, cs, arg2);
Int32 idx = arg1.indexOf(arg2);
if ((idx >= 0)&&(idx<arg1.length())) {
arg2.clear();
arg1.subString(0,idx,arg2);
result = new StringResult(arg2);
break;
}
}
result = new StringResult("");
break;
case TRANSLATE:
if ( requireParams(3, 3, cs) ) {
String src, oldChars, newChars;
evaluateToString((Expr*)iter->next(),context, cs, src);
evaluateToString((Expr*)iter->next(),context, cs, oldChars);
evaluateToString((Expr*)iter->next(),context, cs, newChars);
Int32 size = src.length();
UNICODE_CHAR* chars = src.toUnicode(new UNICODE_CHAR[size]);
src.clear();
Int32 newIdx = 0;
Int32 i;
for (i = 0; i < size; i++) {
Int32 idx = oldChars.indexOf(chars[i]);
if (idx >= 0) {
char nchar = newChars.charAt(idx);
if (nchar != -1) src.append(nchar);
}
else src.append(chars[i]);
}
delete chars;
return new StringResult(src);
}
result = new StringResult("");
break;
default : //-- string( object? )
if ( requireParams(0, 1, cs) ) {
String resultStr;
if (iter->hasNext()) {
evaluateToString((Expr*)iter->next(),context, cs, resultStr);
}
else {
String temp;
XMLDOMUtils::getNodeValue(context, &temp);
if ( cs->isStripSpaceAllowed(context) ) {
XMLUtils::stripSpace(temp, resultStr);
}
else resultStr.append(temp);
}
result = new StringResult(resultStr);
}
else result = new StringResult("");
break;
}
delete iter;
return result;
} //-- evaluate

View File

@@ -0,0 +1,96 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: StringResult.cpp,v 1.1 2000-04-06 07:45:44 kvisco%ziplink.net Exp $
*/
/**
* StringResult
* Represents a String as a Result of evaluating an Expr
* @author <a href="mailto:kvisco@ziplink.net">Keith Visco</a>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:44 $
**/
#include "ExprResult.h"
/**
* Default Constructor
**/
StringResult::StringResult() {
} //-- StringResult
/**
* Creates a new StringResult with the value of the given String parameter
* @param str the String to use for initialization of this StringResult's value
**/
StringResult::StringResult(String& str) {
//-- copy str
this->value = str;
} //-- StringResult
/**
* Creates a new StringResult with the value of the given String parameter
* @param str the String to use for initialization of this StringResult's value
**/
StringResult::StringResult(const String& str) {
//-- copy str
this->value = str;
} //-- StringResult
/**
* Returns the value of this StringResult
**/
String& StringResult::getValue() {
return this->value;
} //-- getValue
/**
* Sets the value of this StringResult
* @param str the String to use for this StringResult's value
**/
void StringResult::setValue(const String& str){
// copy str
this->value = str;
} //-- setValue
/*
* Virtual Methods from ExprResult
*/
short StringResult::getResultType() {
return ExprResult::STRING;
} //-- getResultType
void StringResult::stringValue(String& str) {
str.append(this->value);
} //-- stringValue
MBool StringResult::booleanValue() {
return (MBool)(this->value.length());
} //-- booleanValue
double StringResult::numberValue() {
Double dbl(value);
return dbl.doubleValue();
} //-- numberValue

View File

@@ -0,0 +1,94 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: TextExpr.cpp,v 1.1 2000-04-06 07:45:49 kvisco%ziplink.net Exp $
*/
#include "Expr.h"
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* TextExpr::evaluate(Node* context, ContextState* cs) {
NodeSet* nodeSet = new NodeSet();
if ( !context ) return nodeSet;
NodeList* nl = context->getChildNodes();
for (int i = 0; i < nl->getLength(); i++ ) {
Node* node = nl->item(i);
if ( node->getNodeType() == Node::TEXT_NODE )
nodeSet->add(node);
}
return nodeSet;
} //-- evaluate
/**
* Returns the default priority of this Pattern based on the given Node,
* context Node, and ContextState.
* If this pattern does not match the given Node under the current context Node and
* ContextState then Negative Infinity is returned.
**/
double TextExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
return -0.5;
} //-- getDefaultPriority
/**
* Returns the type of this NodeExpr
* @return the type of this NodeExpr
**/
short TextExpr::getType() {
return NodeExpr::TEXT_EXPR;
} //-- getType
/**
* Determines whether this NodeExpr matches the given node within
* the given context
**/
MBool TextExpr::matches(Node* node, Node* context, ContextState* cs) {
if ( node ) {
return (MBool) (node->getNodeType() == Node::TEXT_NODE);
}
return MB_FALSE;
} //-- matches
/**
* Returns the String representation of this NodeExpr.
* @param dest the String to use when creating the String
* representation. The String representation will be appended to
* any data in the destination String, to allow cascading calls to
* other #toString() methods for Expressions.
* @return the String representation of this NodeExpr.
**/
void TextExpr::toString(String& dest) {
dest.append("text()");
} //-- toString

View File

@@ -0,0 +1,166 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: UnionExpr.cpp,v 1.1 2000-04-06 07:45:52 kvisco%ziplink.net Exp $
*/
#include "Expr.h"
//-------------/
//- UnionExpr -/
//-------------/
/**
* Creates a new UnionExpr
**/
UnionExpr::UnionExpr() {
//-- do nothing
}
/**
* Destructor, will delete all Path Expressions
**/
UnionExpr::~UnionExpr() {
ListIterator* iter = expressions.iterator();
while ( iter->hasNext() ) {
iter->next();
delete (PathExpr*)iter->remove();
}
delete iter;
} //-- ~UnionExpr
/**
* Adds the PathExpr to this UnionExpr
* @param pathExpr the PathExpr to add to this UnionExpr
**/
void UnionExpr::addPathExpr(PathExpr* pathExpr) {
if (pathExpr) expressions.add(pathExpr);
} //-- addPathExpr
/**
* Adds the PathExpr to this UnionExpr
* @param pathExpr the PathExpr to add to this UnionExpr
**/
void UnionExpr::addPathExpr(int index, PathExpr* pathExpr) {
if (pathExpr) expressions.insert(index, pathExpr);
} //-- addPathExpr
//------------------------------------/
//- Virtual methods from PatternExpr -/
//------------------------------------/
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* UnionExpr::evaluate(Node* context, ContextState* cs) {
if ( (!context) || (expressions.getLength() == 0))
return new NodeSet(0);
NodeSet* nodes = new NodeSet();
ListIterator* iter = expressions.iterator();
while ( iter->hasNext() ) {
PathExpr* pExpr = (PathExpr*)iter->next();
NodeSet* tmpNodes = (NodeSet*)pExpr->evaluate(context, cs);
for (int j = 0; j < tmpNodes->size(); j++) {
nodes->add(tmpNodes->get(j));
}
delete tmpNodes;
}
delete iter;
return nodes;
} //-- evaluate
/**
* Returns the default priority of this Pattern based on the given Node,
* context Node, and ContextState.
* If this pattern does not match the given Node under the current context Node and
* ContextState then Negative Infinity is returned.
**/
double UnionExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
//-- find highest priority
double priority = Double::NEGATIVE_INFINITY;
ListIterator* iter = expressions.iterator();
while ( iter->hasNext() ) {
PathExpr* pExpr = (PathExpr*)iter->next();
if ( pExpr->matches(node, context, cs) ) {
double tmpPriority = pExpr->getDefaultPriority(node, context, cs);
priority = (tmpPriority > priority) ? tmpPriority : priority;
}
}
delete iter;
return priority;
} //-- getDefaultPriority
/**
* Determines whether this UnionExpr matches the given node within
* the given context
**/
MBool UnionExpr::matches(Node* node, Node* context, ContextState* cs) {
ListIterator* iter = expressions.iterator();
while ( iter->hasNext() ) {
PathExpr* pExpr = (PathExpr*)iter->next();
if ( pExpr->matches(node, context, cs) ) {
delete iter;
return MB_TRUE;
}
}
delete iter;
return MB_FALSE;
} //-- matches
/**
* Returns the String representation of this PatternExpr.
* @param dest the String to use when creating the String
* representation. The String representation will be appended to
* any data in the destination String, to allow cascading calls to
* other #toString() methods for Expressions.
* @return the String representation of this PatternExpr.
**/
void UnionExpr::toString(String& dest) {
ListIterator* iter = expressions.iterator();
short count = 0;
while ( iter->hasNext() ) {
//-- set operator
if (count > 0) dest.append(" | ");
((PathExpr*)iter->next())->toString(dest);
++count;
}
delete iter;
} //-- toString

View File

@@ -0,0 +1,118 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: VariableRefExpr.cpp,v 1.1 2000-04-06 07:45:55 kvisco%ziplink.net Exp $
*/
#include "Expr.h"
//-------------------/
//- VariableRefExpr -/
//-------------------/
/**
* Default constructor
**/
VariableRefExpr::VariableRefExpr() {
} //-- VariableRefExpr
/**
* Creates a VariableRefExpr with the given variable name
**/
VariableRefExpr::VariableRefExpr(const String& name) {
this->name = name;
} //-- VariableRefExpr
/**
* Creates a VariableRefExpr with the given variable name
**/
VariableRefExpr::VariableRefExpr(String& name) {
this->name = name;
} //-- VariableRefExpr
/**
* Default destructor
**/
VariableRefExpr::~VariableRefExpr() {
} //-- ~VariableRefExpr
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* VariableRefExpr::evaluate(Node* context, ContextState* cs) {
ExprResult* exprResult = cs->getVariable(name);
//-- make copy to prevent deletetion
//-- I know, I should add a #copy method to ExprResult, I will
ExprResult* copyOfResult = 0;
if ( exprResult ) {
switch ( exprResult->getResultType() ) {
//-- BooleanResult
case ExprResult::BOOLEAN :
copyOfResult = new BooleanResult(exprResult->booleanValue());
break;
//-- NodeSet
case ExprResult::NODESET :
{
NodeSet* src = (NodeSet*)exprResult;
NodeSet* dest = new NodeSet(src->size());
for ( int i = 0; i < src->size(); i++)
dest->add(src->get(i));
copyOfResult = dest;
break;
}
//-- NumberResult
case ExprResult::NUMBER :
copyOfResult = new NumberResult(exprResult->numberValue());
break;
//-- StringResult
default:
StringResult* strResult = new StringResult();
exprResult->stringValue(strResult->getValue());
copyOfResult = strResult;
break;
}
}
else copyOfResult = new StringResult();
return copyOfResult;
} //-- evaluate
/**
* Returns the String representation of this Expr.
* @param dest the String to use when creating the String
* representation. The String representation will be appended to
* any data in the destination String, to allow cascading calls to
* other #toString() methods for Expressions.
* @return the String representation of this Expr.
**/
void VariableRefExpr::toString(String& str) {
str.append('$');
str.append(name);
} //-- toString

View File

@@ -0,0 +1,100 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: WildCardExpr.cpp,v 1.1 2000-04-06 07:46:00 kvisco%ziplink.net Exp $
*/
#include "Expr.h"
/**
* This class represents a WildCardExpr as defined by the XSL
* Working Draft
* @author <A HREF="mailto:kvisco@ziplink.net">Keith Visco</A>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:46:00 $
**/
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param ps the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
**/
ExprResult* WildCardExpr::evaluate(Node* context, ContextState* cs) {
NodeSet* nodeSet = new NodeSet();
if ( !context ) return nodeSet;
NodeList* nl = context->getChildNodes();
for (int i = 0; i < nl->getLength(); i++ ) {
Node* node = nl->item(i);
if ( node->getNodeType() == Node::ELEMENT_NODE )
nodeSet->add(node);
}
return nodeSet;
} //-- evaluate
/**
* Returns the default priority of this Pattern based on the given Node,
* context Node, and ContextState.
* If this pattern does not match the given Node under the current context Node and
* ContextState then Negative Infinity is returned.
**/
double WildCardExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
return -0.5;
} //-- getDefaultPriority
/**
* Returns the type of this NodeExpr
* @return the type of this NodeExpr
**/
short WildCardExpr::getType() {
return NodeExpr::WILD_CARD;
} //-- getType
/**
* Determines whether this NodeExpr matches the given node within
* the given context
**/
MBool WildCardExpr::matches(Node* node, Node* context, ContextState* cs) {
if ( node ) {
return (MBool) (node->getNodeType() == Node::ELEMENT_NODE);
}
return MB_FALSE;
} //-- matches
/**
* Returns the String representation of this NodeExpr.
* @param dest the String to use when creating the String
* representation. The String representation will be appended to
* any data in the destination String, to allow cascading calls to
* other #toString() methods for Expressions.
* @return the String representation of this NodeExpr.
**/
void WildCardExpr::toString(String& dest) {
dest.append("*");
} //-- toString

View File

@@ -0,0 +1,64 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: XPathNames.cpp,v 1.1 2000-04-06 07:46:08 kvisco%ziplink.net Exp $
*/
/**
* XPath names
* @author <a href="mailto:kvisco@ziplink.net">Keith Visco</a>
* @version $Revision: 1.1 $ $Date: 2000-04-06 07:46:08 $
**/
#include "FunctionLib.h"
//-- Function Names
const String XPathNames::BOOLEAN_FN = "boolean";
const String XPathNames::CONCAT_FN = "concat";
const String XPathNames::CONTAINS_FN = "contains";
const String XPathNames::COUNT_FN = "count";
const String XPathNames::FALSE_FN = "false";
const String XPathNames::LAST_FN = "last";
const String XPathNames::LOCAL_NAME_FN = "local-name";
const String XPathNames::NAME_FN = "name";
const String XPathNames::NAMESPACE_URI_FN = "namespace-uri";
const String XPathNames::NOT_FN = "not";
const String XPathNames::POSITION_FN = "position";
const String XPathNames::STARTS_WITH_FN = "starts-with";
const String XPathNames::STRING_FN = "string";
const String XPathNames::STRING_LENGTH_FN = "string-length";
const String XPathNames::SUBSTRING_FN = "substring";
const String XPathNames::SUBSTRING_AFTER_FN = "substring-after";
const String XPathNames::SUBSTRING_BEFORE_FN = "substring-before";
const String XPathNames::TRANSLATE_FN = "translate";
const String XPathNames::TRUE_FN = "true";
// OG+
const String XPathNames::NUMBER_FN = "number";
const String XPathNames::ROUND_FN = "round";
const String XPathNames::CEILING_FN = "ceiling";
const String XPathNames::FLOOR_FN = "floor";
// OG-
//-- internal XSL processor functions
const String XPathNames::ERROR_FN = "error";

View File

@@ -0,0 +1,115 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..\..\..\..\..
LIBRARY_NAME=transformix_xpath
MODULE=transformix
REQUIRES=xpcom raptor
CPPSRCS= \
AdditiveExpr.cpp \
AttributeExpr.cpp \
AttributeValueTemplate.cpp \
BasicNodeExpr.cpp \
BooleanFunctionCall.cpp \
BooleanResult.cpp \
ElementExpr.cpp \
ErrorFunctionCall.cpp \
ExprLexer.cpp \
ExprParser.cpp \
FilterExpr.cpp \
FunctionCall.cpp \
IdentityExpr.cpp \
LocationStep.cpp \
MultiplicativeExpr.cpp \
NodeSet.cpp \
NodeSetFunctionCall.cpp \
NumberExpr.cpp \
NumberFunctionCall.cpp \
NumberResult.cpp \
ParentExpr.cpp \
PathExpr.cpp \
PredicateList.cpp \
RelationalExpr.cpp \
RootExpr.cpp \
StringExpr.cpp \
StringFunctionCall.cpp \
StringResult.cpp \
TextExpr.cpp \
UnionExpr.cpp \
VariableRefExpr.cpp \
WildCardExpr.cpp \
$(NULL)
CPP_OBJS= \
.\$(OBJDIR)\AdditiveExpr.obj \
.\$(OBJDIR)\AttributeExpr.obj \
.\$(OBJDIR)\AttributeValueTemplate.obj \
.\$(OBJDIR)\BasicNodeExpr.obj \
.\$(OBJDIR)\BooleanFunctionCall.obj \
.\$(OBJDIR)\BooleanResult.obj \
.\$(OBJDIR)\ElementExpr.obj \
.\$(OBJDIR)\ErrorFunctionCall.obj \
.\$(OBJDIR)\ExprLexer.obj \
.\$(OBJDIR)\ExprParser.obj \
.\$(OBJDIR)\FilterExpr.obj \
.\$(OBJDIR)\FunctionCall.obj \
.\$(OBJDIR)\IdentityExpr.obj \
.\$(OBJDIR)\LocationStep.obj \
.\$(OBJDIR)\MultiplicativeExpr.obj \
.\$(OBJDIR)\NodeSet.obj \
.\$(OBJDIR)\NodeSetFunctionCall.obj \
.\$(OBJDIR)\NumberExpr.obj \
.\$(OBJDIR)\NumberFunctionCall.obj \
.\$(OBJDIR)\NumberResult.obj \
.\$(OBJDIR)\ParentExpr.obj \
.\$(OBJDIR)\PathExpr.obj \
.\$(OBJDIR)\PredicateList.obj \
.\$(OBJDIR)\RelationalExpr.obj \
.\$(OBJDIR)\RootExpr.obj \
.\$(OBJDIR)\StringExpr.obj \
.\$(OBJDIR)\StringFunctionCall.obj \
.\$(OBJDIR)\StringResult.obj \
.\$(OBJDIR)\TextExpr.obj \
.\$(OBJDIR)\UnionExpr.obj \
.\$(OBJDIR)\VariableRefExpr.obj \
.\$(OBJDIR)\WildCardExpr.obj \
$(NULL)
EXPORTS = \
$(NULL)
LINCS=-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor -I..\..\base -I..\util -I..\..\xml\dom \
-I..\..\xml -I ..\..\xsl
LCFLAGS = \
$(LCFLAGS) \
$(DEFINES) \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(LIBRARY)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
clobber::
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

Binary file not shown.

View File

@@ -0,0 +1,30 @@
CC := g++ -g
ROOT_PATH = ../..
BASE_PATH = $(ROOT_PATH)/base
XML_PATH = $(ROOT_PATH)/xml
DOM_PATH = $(XML_PATH)/dom
XSL_PATH = $(ROOT_PATH)/xsl
XSLUTIL_PATH = $(XSL_PATH)/util
INCLUDE_PATHS = -I. \
-I$(BASE_PATH) \
-I$(XSLUTIL_PATH) \
-I$(DOM_PATH) \
-I$(XML_PATH) \
-I$(XSL_PATH) \
-I-
OBJS = *.o \
$(BASE_PATH)/*.o \
$(XSLUTIL_PATH)/*.o \
$(DOM_PATH)/*.o \
$(XML_PATH)/*.o \
$(XSL_PATH)/Names.o
target:
$(CC) $(INCLUDE_PATHS) $(OBJS) parser.cpp -o parser.exe