| //===-- hlvm/Reader/XML/XMLReader.cpp - AST XML Reader Class ----*- C++ -*-===// |
| // |
| // High Level Virtual Machine (HLVM) |
| // |
| // Copyright (C) 2006 Reid Spencer. All Rights Reserved. |
| // |
| // This software is free software; you can redistribute it and/or modify it |
| // under the terms of the GNU Lesser General Public License as published by |
| // the Free Software Foundation; either version 2.1 of the License, or (at |
| // your option) any later version. |
| // |
| // This software is distributed in the hope that it will be useful, but WITHOUT |
| // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for |
| // more details. |
| // |
| // You should have received a copy of the GNU Lesser General Public License |
| // along with this library in the file named LICENSE.txt; if not, write to the |
| // Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
| // MA 02110-1301 USA |
| // |
| //===----------------------------------------------------------------------===// |
| /// @file hlvm/Reader/XMLReader.cpp |
| /// @author Reid Spencer <rspencer@x10sys.com> |
| /// @date 2006/05/12 |
| /// @since 0.1.0 |
| /// @brief Provides the interface to hlvm::XMLReader |
| //===----------------------------------------------------------------------===// |
| |
| #include <libxml/parser.h> |
| #include <libxml/relaxng.h> |
| #include <hlvm/Reader/XMLReader.h> |
| #include <hlvm/Reader/HLVMTokenizer.h> |
| #include <hlvm/AST/Locator.h> |
| #include <hlvm/Base/Source.h> |
| #include <hlvm/AST/AST.h> |
| #include <hlvm/AST/Bundle.h> |
| #include <hlvm/AST/ContainerType.h> |
| #include <hlvm/AST/Documentation.h> |
| #include <hlvm/AST/Linkables.h> |
| #include <hlvm/AST/Constants.h> |
| #include <hlvm/AST/ControlFlow.h> |
| #include <hlvm/AST/MemoryOps.h> |
| #include <hlvm/AST/InputOutput.h> |
| #include <hlvm/AST/Arithmetic.h> |
| #include <hlvm/AST/BooleanOps.h> |
| #include <hlvm/AST/RealMath.h> |
| #include <hlvm/AST/StringOps.h> |
| #include <hlvm/Base/Assert.h> |
| #include <llvm/ADT/StringExtras.h> |
| #include <vector> |
| #include <string> |
| #include <iostream> |
| |
| using namespace hlvm; |
| using namespace HLVM_Reader; |
| |
| namespace { |
| |
| const char HLVMGrammar[] = |
| #include <hlvm/Reader/HLVM.rng.inc> |
| ; |
| |
| class XMLReaderImpl : public XMLReader { |
| std::string path; |
| AST* ast; |
| xmlDocPtr doc; |
| Locator* loc; |
| URI* uri; |
| Block* block; |
| typedef std::vector<Block*> BlockStack; |
| BlockStack blocks; |
| Function* func; |
| Bundle* bundle; |
| bool isError; |
| public: |
| XMLReaderImpl(const std::string& p) |
| : path(p), ast(0), loc(0), uri(0), block(0), blocks(), func(0), bundle(0), |
| isError(0) |
| { |
| ast = AST::create(); |
| ast->setSystemID(p); |
| uri = ast->new_URI(p); |
| } |
| |
| virtual ~XMLReaderImpl() |
| { |
| if (ast) AST::destroy(ast); |
| if (doc) xmlFreeDoc(doc); |
| } |
| |
| virtual bool read(); |
| virtual AST* get(); |
| |
| std::string lookupToken(int32_t token) const |
| { |
| return HLVMTokenizer::lookup(token); |
| } |
| |
| Locator* getLocator(xmlNodePtr& cur) { |
| if (loc) { |
| if (loc->getLine() == cur->line) |
| return loc; |
| } |
| return loc = ast->new_Locator(uri,cur->line); |
| } |
| |
| inline Type* getType(const std::string& name ); |
| bool checkNewType(const std::string& name, Locator* loc); |
| |
| |
| inline void handleParseError(xmlErrorPtr error); |
| inline void handleValidationError(xmlErrorPtr error); |
| |
| inline void error(Locator* loc, const std::string& msg); |
| |
| inline xmlNodePtr checkDoc(xmlNodePtr cur, Documentable* node); |
| |
| ConstantValue* parseLiteralConstant(xmlNodePtr& cur, const std::string& name, |
| const Type* Ty); |
| Constant* parseConstant (xmlNodePtr& cur); |
| Operator* parseOperator (xmlNodePtr& cur); |
| void parseTree (); |
| Type* parseInteger (xmlNodePtr& cur, bool isSigned); |
| |
| template<class OpClass> |
| OpClass* parse(xmlNodePtr& cur); |
| |
| template<class OpClass> |
| OpClass* parseNilaryOp(xmlNodePtr& cur); |
| template<class OpClass> |
| OpClass* parseUnaryOp(xmlNodePtr& cur); |
| template<class OpClass> |
| OpClass* parseBinaryOp(xmlNodePtr& cur); |
| template<class OpClass> |
| OpClass* parseTernaryOp(xmlNodePtr& cur); |
| template<class OpClass> |
| OpClass* parseMultiOp(xmlNodePtr& cur); |
| |
| inline const char* |
| getAttribute(xmlNodePtr cur,const char*name,bool required = true); |
| inline void getTextContent(xmlNodePtr cur, std::string& buffer); |
| inline bool getNameType( |
| xmlNodePtr& cur, std::string& name,std::string& type, bool required = true); |
| inline Type* createIntrinsicType( |
| const std::string& tname, const std::string& name, Locator* loc); |
| |
| private: |
| }; |
| |
| inline void |
| XMLReaderImpl::handleValidationError(xmlErrorPtr e) |
| { |
| std::cerr << e->file << ":" << e->line << ": validation " << |
| (e->level == XML_ERR_WARNING ? "warning" : |
| (e->level == XML_ERR_ERROR ? "error" : |
| (e->level == XML_ERR_FATAL ? "fatal error" : "message"))) |
| << ": " << e->message << "\n"; |
| } |
| |
| inline void |
| XMLReaderImpl::handleParseError(xmlErrorPtr e) |
| { |
| std::cerr << e->file << ":" << e->line << ": parse " << |
| (e->level == XML_ERR_WARNING ? "warning" : |
| (e->level == XML_ERR_ERROR ? "error" : |
| (e->level == XML_ERR_FATAL ? "fatal error" : "message"))) |
| << ": " << e->message << "\n"; |
| } |
| |
| void |
| ParseHandler(void* userData, xmlErrorPtr error) |
| { |
| XMLReaderImpl* reader = reinterpret_cast<XMLReaderImpl*>(userData); |
| reader->handleParseError(error); |
| } |
| |
| void |
| ValidationHandler(void* userData, xmlErrorPtr error) |
| { |
| XMLReaderImpl* reader = reinterpret_cast<XMLReaderImpl*>(userData); |
| reader->handleValidationError(error); |
| } |
| |
| |
| inline int |
| getToken(const xmlChar* name) |
| { |
| return HLVMTokenizer::recognize(reinterpret_cast<const char*>(name)); |
| } |
| |
| inline int |
| getToken(const char* name) |
| { |
| return HLVMTokenizer::recognize(name); |
| } |
| |
| inline bool |
| skipBlanks(xmlNodePtr &cur, bool skipText = true) |
| { |
| while (cur) { |
| switch (cur->type) { |
| case XML_TEXT_NODE: |
| if (!skipText) |
| return true; |
| /* FALL THROUGH */ |
| case XML_COMMENT_NODE: |
| case XML_PI_NODE: |
| break; |
| default: |
| return true; |
| } |
| cur = cur->next; |
| } |
| return cur != 0; |
| } |
| |
| LinkageKinds |
| recognize_LinkageKinds(const char* str) |
| { |
| switch (getToken(str)) |
| { |
| case TKN_weak : return WeakLinkage; |
| case TKN_appending : return AppendingLinkage; |
| case TKN_external : return ExternalLinkage; |
| case TKN_internal : return InternalLinkage; |
| case TKN_linkonce : return LinkOnceLinkage; |
| default: |
| hlvmDeadCode("Invalid Linkage Type"); |
| } |
| return ExternalLinkage; |
| } |
| |
| uint64_t |
| recognize_nonNegativeInteger(const char* str) |
| { |
| return uint64_t(::atoll(str)); |
| } |
| |
| int64_t |
| recognize_Integer(const char * str) |
| { |
| return ::atoll(str); |
| } |
| |
| inline bool |
| recognize_boolean(const char* str) |
| { |
| switch (getToken(str)) |
| { |
| case TKN_FALSE: return false; |
| case TKN_False: return false; |
| case TKN_false: return false; |
| case TKN_NO: return false; |
| case TKN_No: return false; |
| case TKN_no: return false; |
| case TKN_0: return false; |
| case TKN_TRUE: return true; |
| case TKN_True: return true; |
| case TKN_true: return true; |
| case TKN_YES: return true; |
| case TKN_Yes: return true; |
| case TKN_yes: return true; |
| case TKN_1: return true; |
| default: break; |
| } |
| hlvmDeadCode("Invalid boolean value"); |
| return 0; |
| } |
| |
| inline const char* |
| XMLReaderImpl::getAttribute(xmlNodePtr cur,const char*name,bool required ) |
| { |
| const char* result = reinterpret_cast<const char*>( |
| xmlGetNoNsProp(cur,reinterpret_cast<const xmlChar*>(name))); |
| if (!result && required) { |
| error(getLocator(cur),std::string("Requred Attribute '") + name + |
| "' is missing."); |
| } |
| return result; |
| } |
| |
| inline void |
| XMLReaderImpl::getTextContent(xmlNodePtr cur, std::string& buffer) |
| { |
| buffer.clear(); |
| if (cur) skipBlanks(cur,false); |
| while (cur && cur->type == XML_TEXT_NODE) { |
| buffer += reinterpret_cast<const char*>(cur->content); |
| cur = cur->next; |
| } |
| if (cur) skipBlanks(cur); |
| } |
| |
| inline bool |
| XMLReaderImpl::getNameType( |
| xmlNodePtr& cur, |
| std::string& name, |
| std::string& type, |
| bool required) |
| { |
| name.clear(); |
| type.clear(); |
| const char* nm = getAttribute(cur,"id",required); |
| if (nm) |
| name = nm; |
| const char* ty = getAttribute(cur,"type",required); |
| if (ty) |
| type = ty; |
| return !required || (nm && ty); |
| } |
| |
| inline void |
| XMLReaderImpl::error(Locator* loc, const std::string& msg) |
| { |
| std::string location; |
| if (loc) |
| loc->getLocation(location); |
| else |
| location = "Unknown Location"; |
| std::cerr << location << ": " << msg << "\n"; |
| isError = true; |
| } |
| |
| Type* |
| XMLReaderImpl::getType(const std::string& name) |
| { |
| IntrinsicTypes IT = bundle->getIntrinsicTypesValue(name); |
| if (NoIntrinsicType != IT) |
| return bundle->getIntrinsicType(IT); |
| Type* Ty = bundle->getOrCreateType(name); |
| hlvmAssert(Ty != 0 && "Couldn't get Type!"); |
| return Ty; |
| } |
| |
| bool |
| XMLReaderImpl::checkNewType(const std::string& name, Locator* loc) |
| { |
| bool result = true; |
| if (NoIntrinsicType != bundle->getIntrinsicTypesValue(name)) { |
| error(loc,"Attempt to redefine intrinsic type '" + name + "'"); |
| result = false; |
| } |
| if (Type* Ty = bundle->getType(name)) |
| if (OpaqueType* OTy = llvm::dyn_cast<OpaqueType>(Ty)) |
| if (!OTy->isUnresolved()) { |
| error(loc, "Attempt to redefine type '" + name + "'"); |
| result = false; |
| } |
| return result; |
| } |
| |
| template<> Documentation* |
| XMLReaderImpl::parse<Documentation>(xmlNodePtr& cur) |
| { |
| // Documentation is always optional so don't error out if the |
| // node is not a TKN_doc |
| if (cur && skipBlanks(cur) && getToken(cur->name) == TKN_doc) { |
| xmlBufferPtr buffer = xmlBufferCreate(); |
| xmlNodeDump(buffer,doc,cur,0,0); |
| int length = xmlBufferLength(buffer); |
| std::string |
| str(reinterpret_cast<const char*>(xmlBufferContent(buffer)),length); |
| str.erase(0,5); // Zap the <doc> at the start |
| str.erase(str.length()-6); // Zap the </doc> at the end |
| Documentation* doc = ast->new_Documentation(getLocator(cur)); |
| doc->setDoc(str); |
| xmlBufferFree(buffer); |
| cur = cur->next; |
| return doc; |
| } |
| // Just signal that there's no documentation in this node |
| return 0; |
| } |
| |
| inline xmlNodePtr |
| XMLReaderImpl::checkDoc(xmlNodePtr cur, Documentable* node) |
| { |
| xmlNodePtr child = cur->children; |
| Documentation* theDoc = parse<Documentation>(child); |
| if (theDoc) |
| node->setDoc(theDoc); |
| return child; |
| } |
| |
| ConstantValue* |
| XMLReaderImpl::parseLiteralConstant( |
| xmlNodePtr& cur, |
| const std::string& name, |
| const Type* Ty) |
| { |
| if (!name.empty() && bundle->getConst(name) != 0) { |
| error(getLocator(cur),std::string("Constant '") + name |
| + "' already exists."); |
| return 0; |
| } |
| |
| // skip over blank text to find next element |
| skipBlanks(cur); |
| |
| ConstantValue* C = 0; |
| const char* prefix = 0; |
| int token = getToken(cur->name); |
| switch (token) { |
| case TKN_false: |
| { |
| C = ast->new_ConstantBoolean(name, bundle,Ty,false, getLocator(cur)); |
| break; |
| } |
| case TKN_true: |
| { |
| C = ast->new_ConstantBoolean(name,bundle,Ty,true, getLocator(cur)); |
| break; |
| } |
| case TKN_bool: |
| { |
| std::string buffer; |
| xmlNodePtr child = cur->children; |
| getTextContent(child,buffer); |
| bool value = recognize_boolean( buffer.c_str() ); |
| C = ast->new_ConstantBoolean(name, bundle,Ty,value, getLocator(cur)); |
| break; |
| } |
| case TKN_char: |
| { |
| std::string buffer; |
| xmlNodePtr child = cur->children; |
| getTextContent(child,buffer); |
| C = ast->new_ConstantCharacter(name, bundle,Ty,buffer, getLocator(cur)); |
| break; |
| } |
| case TKN_enum: |
| { |
| std::string value; |
| xmlNodePtr child = cur->children; |
| getTextContent(child,value); |
| C = ast->new_ConstantEnumerator(name,bundle,Ty,value,getLocator(cur)); |
| break; |
| } |
| case TKN_bin: |
| case TKN_oct: |
| case TKN_dec: |
| case TKN_hex: |
| { |
| std::string value; |
| xmlNodePtr child = cur->children; |
| getTextContent(child,value); |
| uint16_t base = (token == TKN_dec ? 10 : (token == TKN_hex ? 16 : |
| (token == TKN_oct ? 8 : (token == TKN_bin ? 2 : 10)))); |
| C = ast->new_ConstantInteger(name,bundle,Ty,value,base,getLocator(cur)); |
| break; |
| } |
| case TKN_flt: |
| case TKN_dbl: |
| case TKN_real: |
| { |
| std::string value; |
| xmlNodePtr child = cur->children; |
| getTextContent(child,value); |
| C = ast->new_ConstantReal(name,bundle,Ty,value,getLocator(cur)); |
| break; |
| } |
| case TKN_str: |
| { |
| std::string value; |
| xmlNodePtr child = cur->children; |
| getTextContent(child,value); |
| C = ast->new_ConstantString(name,bundle,Ty,value,getLocator(cur)); |
| break; |
| } |
| case TKN_ptr: |
| { |
| std::string to = getAttribute(cur,"to"); |
| Constant* referent = bundle->getConst(to); |
| if (!referent) |
| error(loc,"Unkown referent for constant pointer"); |
| C = ast->new_ConstantPointer(name,bundle,Ty,referent,loc); |
| break; |
| } |
| case TKN_arr: |
| { |
| const ArrayType* AT = llvm::cast<ArrayType>(Ty); |
| const Type* ElemType = AT->getElementType(); |
| xmlNodePtr child = cur->children; |
| std::vector<ConstantValue*> elems; |
| while (child && skipBlanks(child) && child->type == XML_ELEMENT_NODE) { |
| ConstantValue* elem = parseLiteralConstant(child,"",ElemType); |
| elems.push_back(elem); |
| child = child->next; |
| } |
| C = ast->new_ConstantArray(name,bundle,AT,elems,getLocator(cur)); |
| break; |
| } |
| case TKN_vect: |
| { |
| const VectorType* VT = llvm::cast<VectorType>(Ty); |
| const Type* ElemType = VT->getElementType(); |
| xmlNodePtr child = cur->children; |
| std::vector<ConstantValue*> elems; |
| while (child && skipBlanks(child) && child->type == XML_ELEMENT_NODE) { |
| ConstantValue* elem = parseLiteralConstant(child,"",ElemType); |
| elems.push_back(elem); |
| child = child->next; |
| } |
| C = ast->new_ConstantVector(name,bundle,VT,elems,getLocator(cur)); |
| break; |
| } |
| case TKN_struct: |
| { |
| const StructureType* ST = llvm::cast<StructureType>(Ty); |
| xmlNodePtr child = cur->children; |
| std::vector<ConstantValue*> fields; |
| StructureType::const_iterator I = ST->begin(); |
| while (child && skipBlanks(child) && child->type == XML_ELEMENT_NODE) { |
| ConstantValue* field = parseLiteralConstant(child,"",(*I)->getType()); |
| fields.push_back(field); |
| child = child->next; |
| ++I; |
| } |
| C = ast->new_ConstantStructure(name,bundle,ST,fields,getLocator(cur)); |
| break; |
| } |
| case TKN_cont: |
| { |
| const ContinuationType* CT = llvm::cast<ContinuationType>(Ty); |
| xmlNodePtr child = cur->children; |
| std::vector<ConstantValue*> fields; |
| ContinuationType::const_iterator I = CT->begin(); |
| while (child && skipBlanks(child) && child->type == XML_ELEMENT_NODE) { |
| ConstantValue* field = parseLiteralConstant(child,"",(*I)->getType()); |
| fields.push_back(field); |
| child = child->next; |
| ++I; |
| } |
| C = ast->new_ConstantContinuation(name,bundle,CT,fields,getLocator(cur)); |
| break; |
| } |
| default: |
| hlvmAssert(!"Invalid kind of constant"); |
| break; |
| } |
| hlvmAssert(C && C->getType() == Ty && "Constant/Type mismatch"); |
| if (C) |
| C->setParent(bundle); |
| return C; |
| } |
| |
| inline Constant* |
| XMLReaderImpl::parseConstant(xmlNodePtr& cur) |
| { |
| hlvmAssert(getToken(cur->name) == TKN_constant); |
| std::string name; |
| std::string type; |
| if (getNameType(cur,name,type)) { |
| Type* Ty = getType(type); |
| xmlNodePtr child = cur->children; |
| Documentation* theDoc = parse<Documentation>(child); |
| Constant* C = parseLiteralConstant(child,name,Ty); |
| if (theDoc) |
| C->setDoc(theDoc); |
| return C; |
| } |
| return 0; |
| } |
| |
| template<> AnyType* |
| XMLReaderImpl::parse<AnyType>(xmlNodePtr& cur) |
| { |
| Locator* loc = getLocator(cur); |
| std::string name = getAttribute(cur,"id"); |
| if (!checkNewType(name,loc)) |
| return 0; |
| xmlNodePtr child = cur->children; |
| Documentation* theDoc = parse<Documentation>(child); |
| AnyType* result = ast->new_AnyType(name,bundle,loc); |
| if (theDoc) |
| result->setDoc(theDoc); |
| return result; |
| } |
| |
| template<> BooleanType* |
| XMLReaderImpl::parse<BooleanType>(xmlNodePtr& cur) |
| { |
| Locator* loc = getLocator(cur); |
| std::string name = getAttribute(cur,"id"); |
| if (!checkNewType(name,loc)) |
| return 0; |
| xmlNodePtr child = cur->children; |
| Documentation* theDoc = parse<Documentation>(child); |
| BooleanType* result = ast->new_BooleanType(name,bundle,loc); |
| if (theDoc) |
| result->setDoc(theDoc); |
| return result; |
| } |
| |
| template<> BufferType* |
| XMLReaderImpl::parse<BufferType>(xmlNodePtr& cur) |
| { |
| Locator* loc = getLocator(cur); |
| std::string name = getAttribute(cur,"id"); |
| if (!checkNewType(name,loc)) |
| return 0; |
| xmlNodePtr child = cur->children; |
| Documentation* theDoc = parse<Documentation>(child); |
| Type* result = ast->new_IntrinsicType(name,bundle,bufferTy,loc); |
| if (theDoc) |
| result->setDoc(theDoc); |
| return llvm::cast<BufferType>(result); |
| } |
| |
| template<> CharacterType* |
| XMLReaderImpl::parse<CharacterType>(xmlNodePtr& cur) |
| { |
| Locator* loc = getLocator(cur); |
| std::string name = getAttribute(cur,"id"); |
| if (!checkNewType(name,loc)) |
| return 0; |
| const char* encoding = getAttribute(cur,"encoding"); |
| xmlNodePtr child = cur->children; |
| Documentation* theDoc = parse<Documentation>(child); |
| std::string enc; |
| if (encoding) |
| enc = encoding; |
| else |
| enc = "utf-8"; |
| CharacterType* result = |
| ast->new_CharacterType(name,bundle,encoding,loc); |
| if (theDoc) |
| result->setDoc(theDoc); |
| return result; |
| } |
| |
| Type* |
| XMLReaderImpl::parseInteger(xmlNodePtr& cur, bool isSigned) |
| { |
| Locator* loc = getLocator(cur); |
| std::string name = getAttribute(cur,"id"); |
| if (!checkNewType(name,loc)) |
| return 0; |
| const char* bits = getAttribute(cur,"bits"); |
| xmlNodePtr child = cur->children; |
| Documentation* theDoc = parse<Documentation>(child); |
| uint64_t numBits = 0; |
| if (bits) |
| numBits = recognize_nonNegativeInteger(bits); |
| else |
| numBits = 32; |
| IntegerType* result = |
| ast->new_IntegerType(name,bundle,numBits,isSigned,loc); |
| if (theDoc) |
| result->setDoc(theDoc); |
| return result; |
| } |
| |
| template<> RangeType* |
| XMLReaderImpl::parse<RangeType>(xmlNodePtr& cur) |
| { |
| Locator* loc = getLocator(cur); |
| std::string name = getAttribute(cur,"id"); |
| if (!checkNewType(name,loc)) |
| return 0; |
| const char* min = getAttribute(cur, "min"); |
| const char* max = getAttribute(cur, "max"); |
| xmlNodePtr child = cur->children; |
| Documentation* theDoc = parse<Documentation>(child); |
| if (min && max) { |
| int64_t minVal = recognize_Integer(min); |
| int64_t maxVal = recognize_Integer(max); |
| RangeType* result = ast->new_RangeType(name,bundle,minVal,maxVal,loc); |
| if (theDoc) |
| result->setDoc(theDoc); |
| return result; |
| } |
| error(loc,"Invalid min/max specification"); |
| return 0; |
| } |
| |
| template<> RealType* |
| XMLReaderImpl::parse<RealType>(xmlNodePtr& cur) |
| { |
| Locator* loc = getLocator(cur); |
| std::string name = getAttribute(cur,"id"); |
| if (!checkNewType(name,loc)) |
| return 0; |
| const char* mantissa = getAttribute(cur, "mantissa"); |
| const char* exponent = getAttribute(cur, "exponent"); |
| xmlNodePtr child = cur->children; |
| Documentation* theDoc = parse<Documentation>(child); |
| if (mantissa && exponent) { |
| int32_t mantVal = recognize_nonNegativeInteger(mantissa); |
| int32_t expoVal = recognize_nonNegativeInteger(exponent); |
| RealType* result = ast->new_RealType(name,bundle,mantVal,expoVal,loc); |
| if (theDoc) |
| result->setDoc(theDoc); |
| return result; |
| } |
| error(loc,"Invalid mantissa/exponent specification"); |
| return 0; |
| } |
| |
| template<> EnumerationType* |
| XMLReaderImpl::parse<EnumerationType>(xmlNodePtr& cur) |
| { |
| hlvmAssert(getToken(cur->name)==TKN_enumeration); |
| Locator* loc = getLocator(cur); |
| std::string name = getAttribute(cur,"id"); |
| if (!checkNewType(name,loc)) |
| return 0; |
| EnumerationType* en = ast->new_EnumerationType(name,bundle,loc); |
| xmlNodePtr child = checkDoc(cur,en); |
| while (child && skipBlanks(child) && child->type == XML_ELEMENT_NODE) { |
| hlvmAssert(getToken(child->name) == TKN_enumerator); |
| std::string id = getAttribute(child,"id"); |
| en->addEnumerator(id); |
| child = child->next; |
| } |
| return en; |
| } |
| |
| template<> PointerType* |
| XMLReaderImpl::parse<PointerType>(xmlNodePtr& cur) |
| { |
| hlvmAssert(getToken(cur->name)==TKN_pointer); |
| Locator* loc = getLocator(cur); |
| std::string name = getAttribute(cur,"id"); |
| if (!checkNewType(name,loc)) |
| return 0; |
| std::string type = getAttribute(cur,"to"); |
| PointerType* result = |
| ast->new_PointerType(name,bundle,getType(type),loc); |
| checkDoc(cur,result); |
| return result; |
| } |
| |
| template<> ArrayType* |
| XMLReaderImpl::parse<ArrayType>(xmlNodePtr& cur) |
| { |
| hlvmAssert(getToken(cur->name)==TKN_array); |
| Locator* loc = getLocator(cur); |
| std::string name = getAttribute(cur,"id"); |
| if (!checkNewType(name,loc)) |
| return 0; |
| std::string type = getAttribute(cur,"of"); |
| const char* len = getAttribute(cur,"length"); |
| ArrayType* result = ast->new_ArrayType( |
| name, bundle, getType(type), recognize_nonNegativeInteger(len),loc); |
| checkDoc(cur,result); |
| return result; |
| } |
| |
| template<> VectorType* |
| XMLReaderImpl::parse<VectorType>(xmlNodePtr& cur) |
| { |
| hlvmAssert(getToken(cur->name)==TKN_vector); |
| Locator* loc = getLocator(cur); |
| std::string name = getAttribute(cur,"id"); |
| if (!checkNewType(name,loc)) |
| return 0; |
| std::string type = getAttribute(cur,"of"); |
| const char* len = getAttribute(cur,"length"); |
| VectorType* result = ast->new_VectorType( |
| name, bundle, getType(type), recognize_nonNegativeInteger(len),loc); |
| checkDoc(cur,result); |
| return result; |
| } |
| |
| template<> StreamType* |
| XMLReaderImpl::parse<StreamType>(xmlNodePtr& cur) |
| { |
| Locator* loc = getLocator(cur); |
| std::string name = getAttribute(cur,"id"); |
| if (!checkNewType(name,loc)) |
| return 0; |
| xmlNodePtr child = cur->children; |
| Documentation* theDoc = parse<Documentation>(child); |
| Type* result = ast->new_IntrinsicType(name,bundle,streamTy,loc); |
| if (theDoc) |
| result->setDoc(theDoc); |
| return llvm::cast<StreamType>(result); |
| } |
| |
| template<> StringType* |
| XMLReaderImpl::parse<StringType>(xmlNodePtr& cur) |
| { |
| Locator* loc = getLocator(cur); |
| std::string name = getAttribute(cur,"id"); |
| if (!checkNewType(name,loc)) |
| return 0; |
| const char* encoding = getAttribute(cur,"encoding"); |
| xmlNodePtr child = cur->children; |
| Documentation* theDoc = parse<Documentation>(child); |
| std::string enc; |
| if (encoding) |
| enc = encoding; |
| else |
| enc = "utf-8"; |
| StringType* result = |
| ast->new_StringType(name,bundle,encoding,loc); |
| if (theDoc) |
| result->setDoc(theDoc); |
| return result; |
| } |
| |
| template<> StructureType* |
| XMLReaderImpl::parse<StructureType>(xmlNodePtr& cur) |
| { |
| hlvmAssert(getToken(cur->name)==TKN_structure); |
| Locator* loc = getLocator(cur); |
| std::string name = getAttribute(cur,"id"); |
| if (!checkNewType(name,loc)) |
| return 0; |
| StructureType* struc = ast->new_StructureType(name, bundle, loc); |
| xmlNodePtr child = checkDoc(cur,struc); |
| while (child && skipBlanks(child) && child->type == XML_ELEMENT_NODE) { |
| hlvmAssert(getToken(child->name) == TKN_field && |
| "Structure only has fields"); |
| std::string name = getAttribute(child,"id"); |
| std::string type = getAttribute(child,"type"); |
| Locator* fldLoc = getLocator(child); |
| Field* fld = ast->new_Field(name, getType(type),fldLoc); |
| struc->addField(fld); |
| checkDoc(child,fld); |
| child = child->next; |
| } |
| return struc; |
| } |
| |
| template<> ContinuationType* |
| XMLReaderImpl::parse<ContinuationType>(xmlNodePtr& cur) |
| { |
| hlvmAssert(getToken(cur->name)==TKN_structure); |
| Locator* loc = getLocator(cur); |
| std::string name = getAttribute(cur,"id"); |
| if (!checkNewType(name,loc)) |
| return 0; |
| ContinuationType* cont = ast->new_ContinuationType(name, bundle, loc); |
| xmlNodePtr child = checkDoc(cur,cont); |
| while (child && skipBlanks(child) && child->type == XML_ELEMENT_NODE) { |
| hlvmAssert(getToken(child->name) == TKN_field && |
| "Continuation only has fields"); |
| std::string name = getAttribute(child,"id"); |
| std::string type = getAttribute(child,"type"); |
| Locator* fldLoc = getLocator(child); |
| Field* fld = ast->new_Field(name,getType(type),fldLoc); |
| cont->addField(fld); |
| checkDoc(child,fld); |
| child = child->next; |
| } |
| return cont; |
| } |
| |
| template<> SignatureType* |
| XMLReaderImpl::parse<SignatureType>(xmlNodePtr& cur) |
| { |
| hlvmAssert(getToken(cur->name)==TKN_signature); |
| Locator* loc = getLocator(cur); |
| std::string name = getAttribute(cur,"id"); |
| if (!checkNewType(name,loc)) |
| return 0; |
| std::string result = getAttribute(cur,"result"); |
| const char* varargs = getAttribute(cur,"varargs",false); |
| SignatureType* sig = |
| ast->new_SignatureType(name, bundle, getType(result),loc); |
| if (varargs) |
| sig->setIsVarArgs(recognize_boolean(varargs)); |
| xmlNodePtr child = checkDoc(cur,sig); |
| while (child && skipBlanks(child) && child->type == XML_ELEMENT_NODE) { |
| hlvmAssert(getToken(child->name) == TKN_arg && "Signature only has args"); |
| std::string name = getAttribute(child,"id"); |
| std::string type = getAttribute(child,"type"); |
| Locator* paramLoc = getLocator(child); |
| Parameter* param = ast->new_Parameter(name,getType(type),paramLoc); |
| sig->addParameter(param); |
| checkDoc(child,param); |
| child = child->next; |
| } |
| return sig; |
| } |
| |
| template<> TextType* |
| XMLReaderImpl::parse<TextType>(xmlNodePtr& cur) |
| { |
| Locator* loc = getLocator(cur); |
| std::string name = getAttribute(cur,"id"); |
| if (!checkNewType(name,loc)) |
| return 0; |
| xmlNodePtr child = cur->children; |
| Documentation* theDoc = parse<Documentation>(child); |
| Type* result = ast->new_IntrinsicType(name,bundle,textTy,loc); |
| if (theDoc) |
| result->setDoc(theDoc); |
| return llvm::cast<TextType>(result); |
| } |
| |
| template<> OpaqueType* |
| XMLReaderImpl::parse<OpaqueType>(xmlNodePtr& cur) |
| { |
| hlvmAssert(getToken(cur->name)==TKN_opaque); |
| std::string name = getAttribute(cur,"id"); |
| if (!checkNewType(name,loc)) |
| return 0; |
| Locator* loc = getLocator(cur); |
| OpaqueType* result = ast->new_OpaqueType(name, false, bundle, loc); |
| checkDoc(cur,result); |
| return result; |
| } |
| |
| template<> Variable* |
| XMLReaderImpl::parse<Variable>(xmlNodePtr& cur) |
| { |
| hlvmAssert(getToken(cur->name)==TKN_variable); |
| Locator* loc = getLocator(cur); |
| std::string name, type; |
| getNameType(cur, name, type); |
| if (Constant* lkbl = bundle->getConst(name)) |
| error(loc, "Name '" + name + "' is already in use"); |
| const char* cnst = getAttribute(cur, "const", false); |
| const char* lnkg = getAttribute(cur, "linkage", false); |
| const char* init = getAttribute(cur, "init", false); |
| const Type* Ty = getType(type); |
| Variable* var = ast->new_Variable(name, bundle, Ty,loc); |
| if (cnst) |
| var->setIsConstant(recognize_boolean(cnst)); |
| if (lnkg) |
| var->setLinkageKind(recognize_LinkageKinds(lnkg)); |
| if (init) { |
| Constant* initializer = bundle->getConst(init); |
| if (initializer) |
| var->setInitializer(initializer); |
| else |
| error(loc,std::string("Constant '") + init + |
| "' not found in initializer."); |
| } |
| checkDoc(cur,var); |
| return var; |
| } |
| |
| template<> AutoVarOp* |
| XMLReaderImpl::parse<AutoVarOp>(xmlNodePtr& cur) |
| { |
| Locator* loc = getLocator(cur); |
| std::string name, type; |
| getNameType(cur, name, type); |
| const Type* Ty = getType(type); |
| AutoVarOp* result = ast->AST::new_AutoVarOp(name,Ty,loc); |
| xmlNodePtr child = checkDoc(cur,result); |
| if (child && skipBlanks(child)) { |
| Operator* oprnd1 = parseOperator(child); |
| oprnd1->setParent(result); |
| } |
| return result; |
| } |
| |
| template<> GetOp* |
| XMLReaderImpl::parse<GetOp>(xmlNodePtr& cur) |
| { |
| std::string id = getAttribute(cur,"id"); |
| Locator* loc = getLocator(cur); |
| |
| // Find the referrent variable in a block |
| Value* referent = 0; |
| for (BlockStack::reverse_iterator I = blocks.rbegin(), E = blocks.rend(); |
| I != E; ++I ) |
| { |
| Block* blk = *I; |
| if (AutoVarOp* av = blk->getAutoVar(id)) |
| if (av->getName() == id) { |
| referent = av; |
| break; |
| } |
| } |
| |
| // Didn't find an autovar? Try a function argument |
| if (!referent) |
| referent = func->getArgument(id); |
| |
| // Didn't find an autovar? Try a constant value. |
| if (!referent) |
| referent= bundle->getConst(id); |
| |
| // Didn't find an constant? Try an error message for size |
| if (!referent) |
| error(loc,std::string("Referent '") + id + "' not found"); |
| |
| GetOp* refop = ast->AST::new_GetOp(referent, loc); |
| checkDoc(cur,refop); |
| return refop; |
| } |
| |
| template<> GetFieldOp* |
| XMLReaderImpl::parse<GetFieldOp>(xmlNodePtr& cur) |
| { |
| std::string fieldName = getAttribute(cur,"field"); |
| Locator* loc = getLocator(cur); |
| xmlNodePtr child = cur->children; |
| Documentation* doc = parse<Documentation>(child); |
| if (child && skipBlanks(child)) { |
| Operator* oprnd1 = parseOperator(child); |
| GetFieldOp* gfo = ast->AST::new_GetFieldOp(oprnd1,fieldName,loc); |
| if (doc) |
| gfo->setDoc(doc); |
| return gfo; |
| } else { |
| error(loc,std::string("Operator '") + |
| reinterpret_cast<const char*>(cur->name) + "' requires an operand."); |
| } |
| return 0; |
| } |
| |
| template<> GetIndexOp* |
| XMLReaderImpl::parse<GetIndexOp>(xmlNodePtr& cur) |
| { |
| Locator* loc = getLocator(cur); |
| xmlNodePtr child = cur->children; |
| Documentation* doc = parse<Documentation>(child); |
| if (child && skipBlanks(child)) { |
| Operator* oprnd1 = parseOperator(child); |
| child = child->next; |
| if (child && skipBlanks(child)) { |
| Operator* oprnd2 = parseOperator(child); |
| GetIndexOp* gio = ast->AST::new_GetIndexOp(oprnd1,oprnd2,loc); |
| if (doc) |
| gio->setDoc(doc); |
| return gio; |
| } else { |
| error(loc,std::string("Operator '") + |
| reinterpret_cast<const char*>(cur->name) + |
| "' needs a second operand."); |
| } |
| } else { |
| error(loc,std::string("Operator '") + |
| reinterpret_cast<const char*>(cur->name) + "' requires 2 operands."); |
| } |
| return 0; |
| } |
| |
| template<> ConvertOp* |
| XMLReaderImpl::parse<ConvertOp>(xmlNodePtr& cur) |
| { |
| Locator* loc = getLocator(cur); |
| std::string typeName (getAttribute(cur,"type",true)); |
| Type* Ty = getType(typeName); |
| xmlNodePtr child = cur->children; |
| Documentation* doc = parse<Documentation>(child); |
| if (child && skipBlanks(child)) { |
| Operator* oprnd1 = parseOperator(child); |
| ConvertOp* cnvrt = ast->new_ConvertOp(oprnd1,Ty,loc); |
| if (doc) |
| cnvrt->setDoc(doc); |
| return cnvrt; |
| } else { |
| error(loc,std::string("Operator '") + |
| reinterpret_cast<const char*>(cur->name) + "' requires an operand."); |
| } |
| return 0; |
| } |
| |
| template<class OpClass> |
| OpClass* |
| XMLReaderImpl::parseNilaryOp(xmlNodePtr& cur) |
| { |
| Locator* loc = getLocator(cur); |
| xmlNodePtr child = cur->children; |
| Documentation* doc = parse<Documentation>(child); |
| OpClass* result = ast->AST::new_NilaryOp<OpClass>(bundle,loc); |
| if (doc) |
| result->setDoc(doc); |
| return result; |
| } |
| |
| template<class OpClass> |
| OpClass* |
| XMLReaderImpl::parseUnaryOp(xmlNodePtr& cur) |
| { |
| Locator* loc = getLocator(cur); |
| xmlNodePtr child = cur->children; |
| Documentation* doc = parse<Documentation>(child); |
| if (child && skipBlanks(child)) { |
| Operator* oprnd1 = parseOperator(child); |
| OpClass* result = ast->AST::new_UnaryOp<OpClass>(oprnd1,bundle,loc); |
| if (doc) |
| result->setDoc(doc); |
| return result; |
| } else |
| error(loc,std::string("Operator '") + |
| reinterpret_cast<const char*>(cur->name) + "' requires an operand."); |
| return 0; |
| } |
| |
| template<class OpClass> |
| OpClass* |
| XMLReaderImpl::parseBinaryOp(xmlNodePtr& cur) |
| { |
| Locator* loc = getLocator(cur); |
| xmlNodePtr child = cur->children; |
| Documentation* doc = parse<Documentation>(child); |
| if (child && skipBlanks(child)) { |
| Operator* oprnd1 = parseOperator(child); |
| child = child->next; |
| if (child && skipBlanks(child)) { |
| Operator* oprnd2 = parseOperator(child); |
| OpClass* result = |
| ast->AST::new_BinaryOp<OpClass>(oprnd1,oprnd2,bundle,loc); |
| if (doc) |
| result->setDoc(doc); |
| return result; |
| } else { |
| error(loc,std::string("Operator '") + |
| reinterpret_cast<const char*>(cur->name) + |
| "' needs a second operand."); |
| } |
| } else { |
| error(loc,std::string("Operator '") + |
| reinterpret_cast<const char*>(cur->name) + "' requires 2 operands."); |
| } |
| return 0; |
| } |
| |
| template<class OpClass> |
| OpClass* |
| XMLReaderImpl::parseTernaryOp(xmlNodePtr& cur) |
| { |
| Locator* loc = getLocator(cur); |
| xmlNodePtr child = cur->children; |
| Documentation* doc = parse<Documentation>(child); |
| if (child && skipBlanks(child)) { |
| Operator* oprnd1 = parseOperator(child); |
| child = child->next; |
| if (child && skipBlanks(child)) { |
| Operator* oprnd2 = parseOperator(child); |
| child = child->next; |
| if (child && skipBlanks(child)) { |
| Operator* oprnd3 = parseOperator(child); |
| OpClass* result = |
| ast->AST::new_TernaryOp<OpClass>(oprnd1,oprnd2,oprnd3,bundle,loc); |
| if (doc) |
| result->setDoc(doc); |
| return result; |
| } else |
| error(loc,std::string("Operator '") + |
| reinterpret_cast<const char*>(cur->name) + |
| "' needs a third operand."); |
| } else |
| error(loc,std::string("Operator '") + |
| reinterpret_cast<const char*>(cur->name) + |
| "' needs a second operand."); |
| } else |
| error(loc,std::string("Operator '") + |
| reinterpret_cast<const char*>(cur->name) + "' requires 3 operands."); |
| return 0; |
| } |
| |
| template<class OpClass> |
| OpClass* |
| XMLReaderImpl::parseMultiOp(xmlNodePtr& cur) |
| { |
| Locator* loc = getLocator(cur); |
| xmlNodePtr child = cur->children; |
| Documentation* doc = parse<Documentation>(child); |
| MultiOperator::OprndList ol; |
| while (child != 0 && skipBlanks(child)) { |
| Operator* operand = parseOperator(child); |
| if (operand) |
| ol.push_back(operand); |
| else |
| break; |
| child = child->next; |
| } |
| OpClass* result = ast->AST::new_MultiOp<OpClass>(ol,bundle,loc); |
| if (doc) |
| result->setDoc(doc); |
| return result; |
| } |
| |
| template<> Block* |
| XMLReaderImpl::parse<Block>(xmlNodePtr& cur) |
| { |
| hlvmAssert(getToken(cur->name) == TKN_block && "Expecting block element"); |
| hlvmAssert(func != 0); |
| Locator* loc = getLocator(cur); |
| const char* label = getAttribute(cur, "label",false); |
| Block* result = ast->new_Block(loc); |
| xmlNodePtr child = checkDoc(cur,result); |
| MultiOperator::OprndList ops; |
| block = result; |
| if (label) |
| block->setLabel(label); |
| blocks.push_back(block); |
| while (child && skipBlanks(child) && child->type == XML_ELEMENT_NODE) |
| { |
| Operator* op = parseOperator(child); |
| block->addOperand(op); |
| child = child->next; |
| } |
| blocks.pop_back(); |
| if (blocks.empty()) |
| block = 0; |
| else |
| block = blocks.back(); |
| return result; |
| } |
| |
| template<> Function* |
| XMLReaderImpl::parse<Function>(xmlNodePtr& cur) |
| { |
| hlvmAssert(getToken(cur->name)==TKN_function); |
| Locator* loc = getLocator(cur); |
| std::string name, type; |
| getNameType(cur, name, type); |
| Constant* lkbl = bundle->getConst(name); |
| if (lkbl) { |
| if (llvm::isa<Function>(lkbl)) { |
| func = llvm::cast<Function>(lkbl); |
| if (func->hasBlock()) { |
| error(loc,std::string("Function '") + name + "' was already defined."); |
| return func; |
| } |
| } else { |
| error(loc,std::string("Name '") + name + "' was already used."); |
| return 0; |
| } |
| } else { |
| const Type* Ty = getType(type); |
| if (llvm::isa<SignatureType>(Ty)) { |
| func = ast->new_Function(name,bundle,llvm::cast<SignatureType>(Ty),loc); |
| const char* lnkg = getAttribute(cur, "linkage", false); |
| if (lnkg) |
| func->setLinkageKind(recognize_LinkageKinds(lnkg)); |
| } else { |
| error(loc,"Invalid type for a function, must be signature"); |
| } |
| } |
| xmlNodePtr child = checkDoc(cur,func); |
| if (child && skipBlanks(child) && child->type == XML_ELEMENT_NODE) { |
| Block* b = parse<Block>(child); |
| b->setParent(func); |
| } |
| return func; |
| } |
| |
| template<> Program* |
| XMLReaderImpl::parse<Program>(xmlNodePtr& cur) |
| { |
| hlvmAssert(getToken(cur->name) == TKN_program && "Expecting program element"); |
| Locator* loc = getLocator(cur); |
| std::string name(getAttribute(cur, "id")); |
| Program* program = ast->new_Program(name,bundle,loc); |
| func = program; |
| xmlNodePtr child = checkDoc(cur,func); |
| if (child && skipBlanks(child) && child->type == XML_ELEMENT_NODE) { |
| Block* b = parse<Block>(child); |
| b->setParent(func); |
| } else { |
| hlvmDeadCode("Program Without Block!"); |
| } |
| return program; |
| } |
| |
| template<> Import* |
| XMLReaderImpl::parse<Import>(xmlNodePtr& cur) |
| { |
| hlvmAssert(getToken(cur->name)==TKN_import); |
| std::string pfx = getAttribute(cur,"prefix"); |
| Import* imp = ast->new_Import(pfx,getLocator(cur)); |
| checkDoc(cur,imp); |
| return imp; |
| } |
| |
| template<> Bundle* |
| XMLReaderImpl::parse<Bundle>(xmlNodePtr& cur) |
| { |
| hlvmAssert(getToken(cur->name) == TKN_bundle && "Expecting bundle element"); |
| std::string pubid(getAttribute(cur, "id")); |
| Locator* loc = getLocator(cur); |
| bundle = ast->new_Bundle(pubid,loc); |
| xmlNodePtr child = checkDoc(cur,bundle); |
| while (child && skipBlanks(child) && child->type == XML_ELEMENT_NODE) |
| { |
| int tkn = getToken(child->name); |
| Node* n = 0; |
| switch (tkn) { |
| case TKN_array : { n = parse<ArrayType>(child); break; } |
| case TKN_any : { n = parse<AnyType>(child); break; } |
| case TKN_boolean : { n = parse<BooleanType>(child); break; } |
| case TKN_buffer : { n = parse<BufferType>(child); break; } |
| case TKN_character : { n = parse<CharacterType>(child); break; } |
| case TKN_constant : { n = parseConstant(child); break; } |
| case TKN_enumeration : { n = parse<EnumerationType>(child); break; } |
| case TKN_function : { n = parse<Function>(child); break; } |
| case TKN_import : { n = parse<Import>(child); break; } |
| case TKN_opaque : { n = parse<OpaqueType>(child); break; } |
| case TKN_pointer : { n = parse<PointerType>(child); break; } |
| case TKN_program : { n = parse<Program>(child); break; } |
| case TKN_range : { n = parse<RangeType>(child); break; } |
| case TKN_real : { n = parse<RealType>(child); break; } |
| case TKN_signature : { n = parse<SignatureType>(child); break; } |
| case TKN_signed : { n = parseInteger(child,true); break; } |
| case TKN_stream : { n = parse<StreamType>(child); break; } |
| case TKN_string : { n = parse<StringType>(child); break; } |
| case TKN_structure : { n = parse<StructureType>(child); break; } |
| case TKN_text : { n = parse<TextType>(child); break; } |
| case TKN_unsigned : { n = parseInteger(child,false); break; } |
| case TKN_variable : { n = parse<Variable>(child); break; } |
| case TKN_vector : { n = parse<VectorType>(child); break; } |
| default: |
| { |
| hlvmDeadCode("Invalid content for bundle"); |
| break; |
| } |
| } |
| if (n) |
| n->setParent(bundle); |
| child = child->next; |
| } |
| return bundle; |
| } |
| |
| Operator* |
| XMLReaderImpl::parseOperator(xmlNodePtr& cur) |
| { |
| if (cur && skipBlanks(cur) && cur->type == XML_ELEMENT_NODE) { |
| Operator* op = 0; |
| switch (getToken(cur->name)) { |
| case TKN_neg: op = parseUnaryOp<NegateOp>(cur); break; |
| case TKN_cmpl: op = parseUnaryOp<ComplementOp>(cur); break; |
| case TKN_preinc: op = parseUnaryOp<PreIncrOp>(cur); break; |
| case TKN_predec: op = parseUnaryOp<PreDecrOp>(cur); break; |
| case TKN_postinc: op = parseUnaryOp<PostIncrOp>(cur); break; |
| case TKN_postdec: op = parseUnaryOp<PostDecrOp>(cur); break; |
| case TKN_add: op = parseBinaryOp<AddOp>(cur); break; |
| case TKN_sub: op = parseBinaryOp<SubtractOp>(cur); break; |
| case TKN_mul: op = parseBinaryOp<MultiplyOp>(cur); break; |
| case TKN_div: op = parseBinaryOp<DivideOp>(cur); break; |
| case TKN_mod: op = parseBinaryOp<ModuloOp>(cur); break; |
| case TKN_band: op = parseBinaryOp<BAndOp>(cur); break; |
| case TKN_bor: op = parseBinaryOp<BOrOp>(cur); break; |
| case TKN_bxor: op = parseBinaryOp<BXorOp>(cur); break; |
| case TKN_bnor: op = parseBinaryOp<BNorOp>(cur); break; |
| case TKN_not: op = parseUnaryOp<NotOp>(cur); break; |
| case TKN_and: op = parseBinaryOp<AndOp>(cur); break; |
| case TKN_or: op = parseBinaryOp<OrOp>(cur); break; |
| case TKN_nor: op = parseBinaryOp<NorOp>(cur); break; |
| case TKN_xor: op = parseBinaryOp<XorOp>(cur); break; |
| case TKN_eq: op = parseBinaryOp<EqualityOp>(cur); break; |
| case TKN_ne: op = parseBinaryOp<InequalityOp>(cur); break; |
| case TKN_lt: op = parseBinaryOp<LessThanOp>(cur); break; |
| case TKN_gt: op = parseBinaryOp<GreaterThanOp>(cur); break; |
| case TKN_ge: op = parseBinaryOp<GreaterEqualOp>(cur); break; |
| case TKN_le: op = parseBinaryOp<LessEqualOp>(cur); break; |
| case TKN_ispinf: op = parseUnaryOp<IsPInfOp>(cur); break; |
| case TKN_isninf: op = parseUnaryOp<IsNInfOp>(cur); break; |
| case TKN_isnan: op = parseUnaryOp<IsNanOp>(cur); break; |
| case TKN_trunc: op = parseUnaryOp<TruncOp>(cur); break; |
| case TKN_round: op = parseUnaryOp<RoundOp>(cur); break; |
| case TKN_floor: op = parseUnaryOp<FloorOp>(cur); break; |
| case TKN_ceiling: op = parseUnaryOp<CeilingOp>(cur); break; |
| case TKN_loge: op = parseUnaryOp<LogEOp>(cur); break; |
| case TKN_log2: op = parseUnaryOp<Log2Op>(cur); break; |
| case TKN_log10: op = parseUnaryOp<Log10Op>(cur); break; |
| case TKN_squareroot: op = parseUnaryOp<SquareRootOp>(cur); break; |
| case TKN_cuberoot: op = parseUnaryOp<CubeRootOp>(cur); break; |
| case TKN_factorial: op = parseUnaryOp<FactorialOp>(cur); break; |
| case TKN_power: op = parseBinaryOp<PowerOp>(cur); break; |
| case TKN_root: op = parseBinaryOp<RootOp>(cur); break; |
| case TKN_GCD: op = parseBinaryOp<GCDOp>(cur); break; |
| case TKN_LCM: op = parseBinaryOp<LCMOp>(cur); break; |
| case TKN_sinsert: op = parseTernaryOp<StrInsertOp>(cur); break; |
| case TKN_serase: op = parseTernaryOp<StrEraseOp>(cur); break; |
| case TKN_sreplace: op = parseMultiOp<StrReplaceOp>(cur); break; |
| case TKN_sconcat: op = parseBinaryOp<StrConcatOp>(cur); break; |
| case TKN_select: op = parseTernaryOp<SelectOp>(cur); break; |
| case TKN_switch: op = parseMultiOp<SwitchOp>(cur); break; |
| case TKN_while: op = parseBinaryOp<WhileOp>(cur); break; |
| case TKN_unless: op = parseBinaryOp<UnlessOp>(cur); break; |
| case TKN_until: op = parseBinaryOp<UntilOp>(cur); break; |
| case TKN_loop: op = parseTernaryOp<LoopOp>(cur); break; |
| case TKN_break: op = parseNilaryOp<BreakOp>(cur); break; |
| case TKN_continue: op = parseNilaryOp<ContinueOp>(cur); break; |
| case TKN_ret: op = parseNilaryOp<ReturnOp>(cur); break; |
| case TKN_result: op = parseUnaryOp<ResultOp>(cur); break; |
| case TKN_call: op = parseMultiOp<CallOp>(cur); break; |
| case TKN_store: op = parseBinaryOp<StoreOp>(cur); break; |
| case TKN_load: op = parseUnaryOp<LoadOp>(cur); break; |
| case TKN_open: op = parseUnaryOp<OpenOp>(cur); break; |
| case TKN_write: op = parseBinaryOp<WriteOp>(cur); break; |
| case TKN_close: op = parseUnaryOp<CloseOp>(cur); break; |
| case TKN_get: op = parse<GetOp>(cur); break; |
| case TKN_getidx: op = parse<GetIndexOp>(cur); break; |
| case TKN_getfld: op = parse<GetFieldOp>(cur); break; |
| case TKN_convert: op = parse<ConvertOp>(cur); break; |
| case TKN_autovar: op = parse<AutoVarOp>(cur); break; |
| case TKN_block: op = parse<Block>(cur); break; |
| default: |
| hlvmDeadCode("Unrecognized operator"); |
| break; |
| } |
| return op; |
| } else if (cur != 0) |
| hlvmDeadCode("Expecting a value"); |
| return 0; |
| } |
| |
| void |
| XMLReaderImpl::parseTree() |
| { |
| xmlNodePtr cur = xmlDocGetRootElement(doc); |
| if (!cur) { |
| error(0,"No root node"); |
| return; |
| } |
| hlvmAssert(getToken(cur->name) == TKN_hlvm && "Expecting hlvm element"); |
| const std::string pubid = getAttribute(cur,"pubid"); |
| ast->setPublicID(pubid); |
| cur = cur->children; |
| if (skipBlanks(cur)) { |
| Bundle* b = parse<Bundle>(cur); |
| } |
| } |
| |
| // Implement the read interface to parse, validate, and convert the |
| // XML document into AST Nodes. |
| bool |
| XMLReaderImpl::read() { |
| |
| // create the RelaxNG Parser Context |
| xmlRelaxNGParserCtxtPtr rngparser = |
| xmlRelaxNGNewMemParserCtxt(HLVMGrammar, sizeof(HLVMGrammar)); |
| if (!rngparser) { |
| error(0,"Failed to allocate RNG Parser Context"); |
| return false; |
| } |
| |
| // Provide the error handler for parsing the schema |
| xmlRelaxNGSetParserStructuredErrors(rngparser, ParseHandler, this); |
| |
| // Parse the schema and build an internal structure for it |
| xmlRelaxNGPtr schema = xmlRelaxNGParse(rngparser); |
| if (!schema) { |
| error(0,"Failed to parse the RNG Schema"); |
| xmlRelaxNGFreeParserCtxt(rngparser); |
| return false; |
| } |
| |
| // create a document parser context |
| xmlParserCtxtPtr ctxt = xmlNewParserCtxt(); |
| if (!ctxt) { |
| error(0,"Failed to allocate document parser context"); |
| xmlRelaxNGFreeParserCtxt(rngparser); |
| xmlRelaxNGFree(schema); |
| return false; |
| } |
| |
| // Parse the file, creating a Document tree |
| doc = xmlCtxtReadFile(ctxt, path.c_str(), 0, 0); |
| if (!doc) { |
| error(0,"Failed to parse the document"); |
| xmlRelaxNGFreeParserCtxt(rngparser); |
| xmlRelaxNGFree(schema); |
| xmlFreeParserCtxt(ctxt); |
| return false; |
| } |
| |
| // Create a validation context |
| xmlRelaxNGValidCtxtPtr validation = xmlRelaxNGNewValidCtxt(schema); |
| if (!validation) { |
| error(0,"Failed to create the validation context"); |
| xmlRelaxNGFreeParserCtxt(rngparser); |
| xmlRelaxNGFree(schema); |
| xmlFreeParserCtxt(ctxt); |
| xmlFreeDoc(doc); |
| doc = 0; |
| return false; |
| } |
| |
| // Provide the error handler for parsing the schema |
| xmlRelaxNGSetValidStructuredErrors(validation, ValidationHandler, this); |
| |
| // Validate the document with the schema |
| if (xmlRelaxNGValidateDoc(validation, doc)) { |
| error(0,"Document didn't pass RNG schema validation"); |
| xmlRelaxNGFreeParserCtxt(rngparser); |
| xmlRelaxNGFree(schema); |
| xmlFreeParserCtxt(ctxt); |
| xmlFreeDoc(doc); |
| doc = 0; |
| xmlRelaxNGFreeValidCtxt(validation); |
| return false; |
| } |
| |
| // Parse |
| parseTree(); |
| xmlRelaxNGFreeParserCtxt(rngparser); |
| xmlRelaxNGFree(schema); |
| xmlFreeParserCtxt(ctxt); |
| xmlRelaxNGFreeValidCtxt(validation); |
| xmlFreeDoc(doc); |
| doc = 0; |
| return true; |
| } |
| |
| AST* |
| XMLReaderImpl::get() |
| { |
| return ast; |
| } |
| |
| } |
| |
| XMLReader* |
| hlvm::XMLReader::create(const std::string& src) |
| { |
| return new XMLReaderImpl(src); |
| } |