Main Page | Packages | Class Hierarchy | Class List | File List | Class Members

xmlexpr.EvalXML Class Reference

List of all members.

Detailed Description

EvalXML Jul 26, 2004.

Support for evaluating expressions in XML form.

A validated DOM Object is built for the XML expression. The recursive methods in this class walk over the DOM tree and evaluate the expression.

The tree walk reflects the structure of the expression. The expression structure is shown below in BNF like syntax.

        statement: assignment | addExp

        assignment: ident "=" addExp

        addExp: term | addExp addOp addExp

        term: unaryExpr | term mulOp term

        unaryExpr: factor | minus factor

        factor: ident | number | "(" addExp ")"

The XML expression is validated by an XML schema (see expression.xsd).

Expressions may be evaluated by themselves or assigned to a variable. The class supports a basic symbol table to support symbols and their associated values.

Author:
Ian Kaplan, www.bearcave.com, iank@bearcave.com


Public Member Functions

Integer eval (DOMParser parser, byte[] xmlBytes)
 This function is passed an assignment statement or an expression, formatted in XML.

Private Member Functions

ArrayList toElementNodeList (NodeList list)
 A DOM NodeList may include a variety of different node types.
int symbolLookup (String name)
 Given a symbol name, look the symbol up in the symbol table.
void symbolEnter (String name, int value)
 Enter a symbol and its value into the symbol table.
String nodeTypeToString (short type)
 Get the type name associated with the numeric Node type value.
int factor (Node root)
 Evaluate identifiers, numbers or parenthesized expressions (via a recursive call to the addExp method).
int unaryExp (Node root)
 Process a factor or a unary minus expression (the silly unary plus is not supported).
int term (Node root)
 Process a factor expression.
int addExp (Node root)
void store (Node lhs, int value)
 "Store" a value in a symbol
Integer statement (Node root)
 Process and assignment statement or an expression.

Static Private Member Functions

Document bytesToDocument (DOMParser parser, byte[] xmlBytes) throws SAXException, IOException
 Parse the XML into a DOM Document.

Private Attributes

HashMap mSymTab = new HashMap()
 The symbol table consists of a set of String, Integer pairs, where the String object is the key.


Member Function Documentation

int xmlexpr.EvalXML.addExp Node  root  )  [private]
 

           addExp: term | addExp addOp addExp
00329 { 00330 int rslt = 0; 00331 if (root.getLocalName().equals( TokenType.MINUS.toString() ) || 00332 root.getLocalName().equals( TokenType.PLUS.toString() )) { 00333 ArrayList children = toElementNodeList( root.getChildNodes() ); 00334 Node lhs = (Node)children.get( 0 ); 00335 Node rhs = (Node)children.get( 1 ); 00336 int lhsInt = addExp( lhs ); 00337 int rhsInt = addExp( rhs ); 00338 if (root.getLocalName().equals( TokenType.MINUS.toString() )) { 00339 rslt = lhsInt - rhsInt; 00340 } 00341 else { 00342 rslt = lhsInt + rhsInt; 00343 } 00344 } 00345 else { 00346 rslt = term( root ); 00347 } 00348 return rslt; 00349 } // addExp

Document xmlexpr.EvalXML.bytesToDocument DOMParser  parser,
byte[]  xmlBytes
throws SAXException, IOException [static, private]
 

Parse the XML into a DOM Document.

00079 { 00080 ByteArrayInputStream istream = new ByteArrayInputStream( xmlBytes ); 00081 InputSource isource = new InputSource( istream ); 00082 parser.parse( isource ); 00083 Document xmlDoc = parser.getDocument(); 00084 return xmlDoc; 00085 } // bytesToDocument

Integer xmlexpr.EvalXML.eval DOMParser  parser,
byte[]  xmlBytes
 

This function is passed an assignment statement or an expression, formatted in XML.

If the argument is an assignment statement, the right hand side (RHS) value is assigned to the variable on the left hand side (LHS). In the case of an assignment statement the function will return null.

If the argument is an expression the expression will be evaluated. The function will return the result as an Integer object.

00417 { 00418 Integer result = null; 00419 Document doc = null; 00420 try { 00421 doc = bytesToDocument(parser, xmlBytes); 00422 Node root = doc.getDocumentElement(); 00423 if (root.getLocalName().equals("EXPRESSION")) { 00424 ArrayList children = toElementNodeList( root.getChildNodes() ); 00425 root = (Node)children.get( 0 ); 00426 result = statement( root ); 00427 } 00428 else { 00429 System.out.println("eval: EXPRESSION XML Document expected"); 00430 } 00431 } catch (SAXException e) { 00432 String msg = null; 00433 if (e instanceof SAXParseException) { 00434 int lineNum = ((SAXParseException)e).getLineNumber(); 00435 int columnNumber = ((SAXParseException)e).getColumnNumber(); 00436 String exceptionMsg = ((SAXParseException)e).getMessage(); 00437 msg = "Error: line = " + lineNum + ", column = " + columnNumber + ": " + exceptionMsg; 00438 } 00439 else { 00440 msg = "TestXerces.bytesToDocument: SAX Exception = " + e; 00441 } 00442 System.out.println(msg); 00443 } catch (IOException e) { 00444 System.out.println("TestXerces.bytesToDocument: IOException = " + e); 00445 } 00446 return result; 00447 } // eval

int xmlexpr.EvalXML.factor Node  root  )  [private]
 

Evaluate identifiers, numbers or parenthesized expressions (via a recursive call to the addExp method).

       factor: ident | number | paren addExp
00205 { 00206 int rslt = 0; 00207 String tagName = root.getLocalName(); 00208 if (tagName.equals( TokenType.IDENT.toString() ) || 00209 tagName.equals( TokenType.INT.toString() )) { 00210 NodeList children = root.getChildNodes(); 00211 if (children.getLength() == 1) { 00212 Node child = children.item( 0 ); 00213 if (child.getNodeType() == Node.TEXT_NODE) { 00214 Text textNode = (Text)child; 00215 String textData = textNode.getData(); 00216 if (tagName.equals(TokenType.IDENT.toString())) { 00217 rslt = symbolLookup( textData ); 00218 } 00219 else { 00220 try { 00221 rslt = Integer.parseInt( textData ); 00222 } 00223 catch (NumberFormatException e) { 00224 System.out.println("factor: bad format for number \"" + 00225 textData + "\""); 00226 } 00227 } 00228 } 00229 else { 00230 System.out.println("factor: unexpected node type = " + 00231 nodeTypeToString( child.getNodeType() )); 00232 } 00233 } 00234 else { 00235 System.out.println("factor: 1 child expected for " + tagName + ", got " + 00236 children.getLength() + " children"); 00237 } 00238 } // root is not an IDENT or an INT, so it should be an expression 00239 else if (tagName.equals( TokenType.PAREN.toString() )) { 00240 ArrayList children = toElementNodeList( root.getChildNodes() ); 00241 if (children.size() == 1) { 00242 Node expr = (Node)children.get( 0 ); 00243 rslt = addExp( expr ); 00244 } 00245 else { 00246 System.out.println("factor: extra children of PAREN"); 00247 } 00248 } 00249 else { 00250 System.out.println("factor: Unexpected tag = " + tagName ); 00251 } 00252 return rslt; 00253 } // factor

String xmlexpr.EvalXML.nodeTypeToString short  type  )  [private]
 

Get the type name associated with the numeric Node type value.

This method is called from error messages.

00155 { 00156 String typeName = "Unknow Node type"; 00157 if (type == Node.ATTRIBUTE_NODE) { 00158 typeName = "ATTRIBUTE_NODE"; 00159 } 00160 else if (type == Node.CDATA_SECTION_NODE) { 00161 typeName = "CDATA_SECTION_NODE"; 00162 } 00163 else if (type == Node.COMMENT_NODE) { 00164 typeName = "COMMENT_NODE"; 00165 } 00166 else if (type == Node.DOCUMENT_FRAGMENT_NODE) { 00167 typeName = "DOCUMENT_FRAGMENT_NODE"; 00168 } 00169 else if (type == Node.DOCUMENT_NODE) { 00170 typeName = "DOCUMENT_NODE"; 00171 } 00172 else if (type == Node.DOCUMENT_TYPE_NODE) { 00173 typeName = "DOCUMENT_TYPE_NODE"; 00174 } 00175 else if (type == Node.ELEMENT_NODE) { 00176 typeName = "ELEMENT_NODE"; 00177 } 00178 else if (type == Node.ENTITY_NODE) { 00179 typeName = "ENTITY_NODE"; 00180 } 00181 else if (type == Node.ENTITY_REFERENCE_NODE) { 00182 typeName = "ENTITY_REFERENCE_NODE"; 00183 } 00184 else if (type == Node.NOTATION_NODE) { 00185 typeName = "NOTATION_NODE"; 00186 } 00187 else if (type == Node.PROCESSING_INSTRUCTION_NODE) { 00188 typeName = "PROCESSING_INSTRUCTION_NODE"; 00189 } 00190 else if (type == Node.TEXT_NODE ) { 00191 typeName = "TEXT_NODE "; 00192 } 00193 return typeName; 00194 } // nodeTypeToString

Integer xmlexpr.EvalXML.statement Node  root  )  [private]
 

Process and assignment statement or an expression.

          statement: assignment | addExp
00375 { 00376 Integer rslt = null; 00377 Node expr = root; 00378 Node lhs = null; 00379 if (root.getLocalName().equals( TokenType.EQUAL.toString() )) { 00380 ArrayList children = toElementNodeList( root.getChildNodes() ); 00381 int len = children.size(); 00382 if (len == 2) { 00383 lhs = (Node)children.get(0); 00384 expr = (Node)children.get(1); 00385 } 00386 else { 00387 System.out.println("statement: two children expected, got " + len + " instead"); 00388 } 00389 } 00390 else { 00391 expr = root; 00392 } 00393 int expRslt = addExp( expr ); 00394 if (lhs != null) { 00395 store( lhs, expRslt ); 00396 } 00397 else { 00398 rslt = new Integer( expRslt ); 00399 } 00400 return rslt; 00401 } // statement

void xmlexpr.EvalXML.store Node  lhs,
int  value
[private]
 

"Store" a value in a symbol

00357 { 00358 NodeList children = lhs.getChildNodes(); 00359 Node child = children.item( 0 ); 00360 if (child.getNodeType() == Node.TEXT_NODE) { 00361 Text textNode = (Text)child; 00362 String symbolName = textNode.getData(); 00363 symbolEnter( symbolName, value ); 00364 } 00365 } // store

void xmlexpr.EvalXML.symbolEnter String  name,
int  value
[private]
 

Enter a symbol and its value into the symbol table.

Parameters:
name symbol name
value symbol value
00143 { 00144 Integer i = new Integer( value ); 00145 mSymTab.put( name, i ); 00146 } // symbolEnter

int xmlexpr.EvalXML.symbolLookup String  name  )  [private]
 

Given a symbol name, look the symbol up in the symbol table.

Returns:
the value of the symbol, or 0 if the symbol is not found.
00122 { 00123 int symVal = 0; 00124 00125 Integer i = (Integer)mSymTab.get( name ); 00126 if (i != null) { 00127 symVal = i.intValue(); 00128 } 00129 else { 00130 System.out.println("No symbol found for " + name ); 00131 } 00132 return symVal; 00133 } // symbolLookup

int xmlexpr.EvalXML.term Node  root  )  [private]
 

Process a factor expression.

         term: factor | term mulOp term
00292 { 00293 int rslt = 0; 00294 if (root.getLocalName().equals( TokenType.TIMES.toString() ) || 00295 root.getLocalName().equals( TokenType.DIV.toString() ) || 00296 root.getLocalName().equals( TokenType.MOD.toString() )) { 00297 00298 ArrayList children = toElementNodeList( root.getChildNodes() ); 00299 Node lhs = (Node)children.get( 0 ); 00300 Node rhs = (Node)children.get( 1 ); 00301 int lhsInt = term( lhs ); 00302 int rhsInt = term( rhs ); 00303 if (root.getLocalName().equals( TokenType.TIMES.toString() )) { 00304 rslt = lhsInt * rhsInt; 00305 } 00306 else if (root.getLocalName().equals( TokenType.DIV.toString() )) { 00307 if (rhsInt != 0) { // don't allow divide by zero 00308 rslt = lhsInt / rhsInt; 00309 } 00310 } 00311 else { // root.getLocalName().equals( TokenType.MOD ) 00312 if (rhsInt != 0) { // don't allow mod by zero 00313 rslt = lhsInt % rhsInt; 00314 } 00315 } 00316 } 00317 else { 00318 rslt = unaryExp( root ); 00319 } 00320 return rslt; 00321 } // term

ArrayList xmlexpr.EvalXML.toElementNodeList NodeList  list  )  [private]
 

A DOM NodeList may include a variety of different node types.

This is awkward when it comes to expression processing, since most of the time we only care about ELEMENT_NODEs. The toElementNodeList method builds an ArrayList that consists only of ELEMENT_NODES.

Parameters:
list a NodeList of DOM Node objects
Returns:
return a Vector of ELEMENT_TYPE nodes. If there are no element type nodes, the size() of the Vector will zero.
00102 { 00103 ArrayList elemList = new ArrayList(); 00104 if (list != null) { 00105 int len = list.getLength(); 00106 for (int i = 0; i < len; i++) { 00107 if (list.item(i).getNodeType() == Node.ELEMENT_NODE) { 00108 elemList.add( list.item(i) ); 00109 } 00110 } 00111 } 00112 return elemList; 00113 } // toElementNodeList

int xmlexpr.EvalXML.unaryExp Node  root  )  [private]
 

Process a factor or a unary minus expression (the silly unary plus is not supported).

            unaryExp: factor | uminus factor
00264 { 00265 int rslt = 0; 00266 boolean unaryMinus = false; 00267 if (root.getLocalName().equals( TokenType.UMINUS.toString() )) { 00268 ArrayList children = toElementNodeList( root.getChildNodes() ); 00269 if (children.size() == 1) { 00270 unaryMinus = true; 00271 root = (Node)children.get( 0 ); 00272 } 00273 else { 00274 System.out.println("unaryExp: more than one child found for UMINUS"); 00275 } 00276 } 00277 rslt = factor( root ); 00278 if (unaryMinus) { 00279 rslt = -rslt; 00280 } 00281 return rslt; 00282 } // unaryExp


Member Data Documentation

HashMap xmlexpr.EvalXML.mSymTab = new HashMap() [private]
 

The symbol table consists of a set of String, Integer pairs, where the String object is the key.


The documentation for this class was generated from the following file:
Generated on Sat Aug 28 13:09:43 2004 for XmlExpr by doxygen 1.3.8