diff --git a/CMakeLists.txt b/CMakeLists.txt index ebb992c1f4..a26c9b34b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -171,6 +171,7 @@ adios_option(Endian_Reverse "Enable support for Little/Big Endian Interoperabili adios_option(Sodium "Enable support for Sodium for encryption" AUTO) adios_option(Catalyst "Enable support for in situ visualization plugin using ParaView Catalyst" AUTO) adios_option(AWSSDK "Enable support for S3 compatible storage using AWS SDK's S3 module" OFF) +adios_option(Derived_Variable "Enable support for derived variables" OFF) include(${PROJECT_SOURCE_DIR}/cmake/DetectOptions.cmake) if(ADIOS2_HAVE_CUDA OR ADIOS2_HAVE_Kokkos_CUDA) @@ -243,8 +244,8 @@ endif() set(ADIOS2_CONFIG_OPTS DataMan DataSpaces HDF5 HDF5_VOL MHS SST Fortran MPI Python Blosc2 BZip2 LIBPRESSIO MGARD PNG SZ ZFP DAOS IME O_DIRECT Sodium Catalyst SysVShMem UCX - ZeroMQ Profiling Endian_Reverse AWSSDK GPU_Support CUDA Kokkos Kokkos_CUDA - Kokkos_HIP Kokkos_SYCL + ZeroMQ Profiling Endian_Reverse Derived_Variable AWSSDK GPU_Support CUDA Kokkos + Kokkos_CUDA Kokkos_HIP Kokkos_SYCL ) GenerateADIOSHeaderConfig(${ADIOS2_CONFIG_OPTS}) diff --git a/bindings/CXX11/CMakeLists.txt b/bindings/CXX11/CMakeLists.txt index 861764313b..76cf76120b 100644 --- a/bindings/CXX11/CMakeLists.txt +++ b/bindings/CXX11/CMakeLists.txt @@ -37,6 +37,12 @@ target_include_directories(adios2_cxx11 add_library(adios2::cxx11 ALIAS adios2_cxx11) +if (ADIOS2_HAVE_Derived_Variable) + target_sources(adios2_cxx11 PRIVATE + adios2/cxx11/VariableDerived.cpp + ) +endif() + if(ADIOS2_HAVE_MPI) add_library(adios2_cxx11_mpi adios2/cxx11/ADIOSMPI.cpp @@ -79,6 +85,14 @@ install( COMPONENT adios2_cxx11-development ) +if (ADIOS2_HAVE_Derived_Variable) + install( + FILES adios2/cxx11/VariableDerived.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/adios2/cxx11 + COMPONENT adios2_cxx11-development + ) +endif() + install( FILES adios2/cxx11/ADIOS.h adios2/cxx11/ADIOS.inl diff --git a/bindings/CXX11/adios2/cxx11/IO.cpp b/bindings/CXX11/adios2/cxx11/IO.cpp index 8018c06d77..e8edb54528 100644 --- a/bindings/CXX11/adios2/cxx11/IO.cpp +++ b/bindings/CXX11/adios2/cxx11/IO.cpp @@ -179,6 +179,16 @@ VariableNT IO::DefineVariable(const DataType type, const std::string &name, cons } } +#ifdef ADIOS2_HAVE_DERIVED_VARIABLE +VariableDerived IO::DefineDerivedVariable(const std::string &name, const std::string &expression, + const DerivedVarType varType) +{ + helper::CheckForNullptr(m_IO, + "for variable name " + name + ", in call to IO::DefineDerivedVariable"); + + return VariableDerived(&m_IO->DefineDerivedVariable(name, expression, varType)); +} +#endif StructDefinition IO::DefineStruct(const std::string &name, const size_t size) { helper::CheckForNullptr(m_IO, "for struct name " + name + ", in call to IO::DefineStruct"); diff --git a/bindings/CXX11/adios2/cxx11/IO.h b/bindings/CXX11/adios2/cxx11/IO.h index 1702c769f4..2b599e3695 100644 --- a/bindings/CXX11/adios2/cxx11/IO.h +++ b/bindings/CXX11/adios2/cxx11/IO.h @@ -20,6 +20,9 @@ #include "Group.h" #include "Operator.h" #include "Variable.h" +#ifdef ADIOS2_HAVE_DERIVED_VARIABLE +#include "VariableDerived.h" +#endif #include "VariableNT.h" #include "adios2/common/ADIOSMacros.h" #include "adios2/common/ADIOSTypes.h" @@ -151,7 +154,11 @@ class IO Variable DefineVariable(const std::string &name, const Dims &shape = Dims(), const Dims &start = Dims(), const Dims &count = Dims(), const bool constantDims = false); - +#ifdef ADIOS2_HAVE_DERIVED_VARIABLE + VariableDerived + DefineDerivedVariable(const std::string &name, const std::string &expression, + const DerivedVarType varType = DerivedVarType::MetadataOnly); +#endif VariableNT DefineVariable(const DataType type, const std::string &name, const Dims &shape = Dims(), const Dims &start = Dims(), const Dims &count = Dims(), const bool constantDims = false); diff --git a/bindings/CXX11/adios2/cxx11/VariableDerived.cpp b/bindings/CXX11/adios2/cxx11/VariableDerived.cpp new file mode 100644 index 0000000000..ce6a4dc0e5 --- /dev/null +++ b/bindings/CXX11/adios2/cxx11/VariableDerived.cpp @@ -0,0 +1,8 @@ +#include "VariableDerived.h" + +#include "adios2/core/VariableDerived.h" + +namespace adios2 +{ +VariableDerived::VariableDerived(core::VariableDerived *variable) : m_VariableDerived(variable) {} +} // end namespace adios2 diff --git a/bindings/CXX11/adios2/cxx11/VariableDerived.h b/bindings/CXX11/adios2/cxx11/VariableDerived.h new file mode 100644 index 0000000000..cc69273c2e --- /dev/null +++ b/bindings/CXX11/adios2/cxx11/VariableDerived.h @@ -0,0 +1,43 @@ +#ifndef ADIOS2_BINDINGS_CXX11_VARIABLE_DERIVED_H_ +#define ADIOS2_BINDINGS_CXX11_VARIABLE_DERIVED_H_ + +#include "Operator.h" +#include "adios2/common/ADIOSTypes.h" + +namespace adios2 +{ + +/// \cond EXCLUDE_FROM_DOXYGEN +// forward declare +class IO; // friend +namespace core +{ + +class VariableDerived; // private implementation +} +/// \endcond + +class VariableDerived +{ + friend class IO; + +public: + /** + * Empty (default) constructor, use it as a placeholder for future + * variables from IO:DefineVariableDerived or IO:InquireVariableDerived. + * Can be used with STL containers. + */ + VariableDerived() = default; + + /** Default, using RAII STL containers */ + ~VariableDerived() = default; + +private: + core::VariableDerived *m_VariableDerived = nullptr; + + VariableDerived(core::VariableDerived *variable); +}; + +} // end namespace adios2 + +#endif // ADIOS2_BINDINGS_CXX11_VARIABLE_DERIVED_H_ diff --git a/cmake/DetectOptions.cmake b/cmake/DetectOptions.cmake index 615995b713..efecb57624 100644 --- a/cmake/DetectOptions.cmake +++ b/cmake/DetectOptions.cmake @@ -196,6 +196,10 @@ endif() set(mpi_find_components C) +if(ADIOS2_USE_Derived_Variable) + set(ADIOS2_HAVE_Derived_Variable TRUE) +endif() + if(ADIOS2_USE_Kokkos AND ADIOS2_USE_CUDA) message(FATAL_ERROR "ADIOS2_USE_Kokkos is incompatible with ADIOS2_USE_CUDA") endif() diff --git a/source/adios2/CMakeLists.txt b/source/adios2/CMakeLists.txt index 343c70d421..355db2992d 100644 --- a/source/adios2/CMakeLists.txt +++ b/source/adios2/CMakeLists.txt @@ -127,6 +127,21 @@ add_library(adios2_core set_property(TARGET adios2_core PROPERTY EXPORT_NAME core) set_property(TARGET adios2_core PROPERTY OUTPUT_NAME adios2${ADIOS2_LIBRARY_SUFFIX}_core) +set(maybe_adios2_core_derived) +if (ADIOS2_HAVE_Derived_Variable) + target_sources(adios2_core PRIVATE + core/VariableDerived.cpp + toolkit/derived/Expression.cpp + toolkit/derived/Function.cpp toolkit/derived/Function.tcc + toolkit/derived/ExprHelper.h) + add_library(adios2_core_derived + toolkit/derived/parser/lexer.cpp + toolkit/derived/parser/parser.cpp + toolkit/derived/parser/ASTNode.cpp) + target_link_libraries(adios2_core PRIVATE adios2_core_derived) + set(maybe_adios2_core_derived adios2_core_derived) +endif() + set(maybe_adios2_core_cuda) if(ADIOS2_HAVE_CUDA) add_library(adios2_core_cuda helper/adiosCUDA.cu) @@ -447,10 +462,11 @@ install(DIRECTORY toolkit/ PATTERN "*/*.inl" REGEX "sst/util" EXCLUDE REGEX "sst/dp" EXCLUDE + REGEX "derived/parser" EXCLUDE ) # Library installation -install(TARGETS adios2_core ${maybe_adios2_core_mpi} ${maybe_adios2_core_cuda} ${maybe_adios2_core_kokkos} ${maybe_adios2_blosc2} EXPORT adios2Exports +install(TARGETS adios2_core ${maybe_adios2_core_mpi} ${maybe_adios2_core_cuda} ${maybe_adios2_core_kokkos} ${maybe_adios2_blosc2} ${maybe_adios2_core_derived} EXPORT adios2Exports RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT adios2_core-runtime LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT adios2_core-libraries NAMELINK_COMPONENT adios2_core-development ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT adios2_core-development diff --git a/source/adios2/common/ADIOSTypes.h b/source/adios2/common/ADIOSTypes.h index 7697c34624..01423e781f 100644 --- a/source/adios2/common/ADIOSTypes.h +++ b/source/adios2/common/ADIOSTypes.h @@ -32,6 +32,16 @@ namespace adios2 { +#ifdef ADIOS2_HAVE_DERIVED_VARIABLE +/** Type of derived variables */ +enum class DerivedVarType +{ + MetadataOnly, ///< Store only the metadata (default) + ExpressionString, ///< Store only the expression string + StoreData ///< Store data and metadata +}; +#endif + /** Memory space for the user provided buffers */ enum class MemorySpace { diff --git a/source/adios2/core/IO.cpp b/source/adios2/core/IO.cpp index 1b99463b54..6b9faf01e9 100644 --- a/source/adios2/core/IO.cpp +++ b/source/adios2/core/IO.cpp @@ -288,6 +288,9 @@ void IO::SetTransportParameter(const size_t transportIndex, const std::string ke } const VarMap &IO::GetVariables() const noexcept { return m_Variables; } +#ifdef ADIOS2_HAVE_DERIVED_VARIABLE +const VarMap &IO::GetDerivedVariables() const noexcept { return m_VariablesDerived; } +#endif const AttrMap &IO::GetAttributes() const noexcept { return m_Attributes; } @@ -808,6 +811,92 @@ void IO::CheckTransportType(const std::string type) const } } +#ifdef ADIOS2_HAVE_DERIVED_VARIABLE +VariableDerived &IO::DefineDerivedVariable(const std::string &name, const std::string &exp_string, + const DerivedVarType varType) +{ + PERFSTUBS_SCOPED_TIMER("IO::DefineDerivedVariable"); + + { + auto itVariable = m_VariablesDerived.find(name); + if (itVariable != m_VariablesDerived.end()) + { + helper::Throw("Core", "IO", "DefineDerivedVariable", + "derived variable " + name + + " already defined in IO " + m_Name); + } + else + { + auto itVariable = m_Variables.find(name); + if (itVariable != m_Variables.end()) + { + helper::Throw( + "Core", "IO", "DefineDerivedVariable", + "derived variable " + name + + " trying to use an already defined variable name in IO " + m_Name); + } + } + } + + derived::Expression derived_exp(exp_string); + std::vector var_list = derived_exp.VariableNameList(); + DataType expressionType = DataType::None; + bool isConstant = true; + std::map> name_to_dims; + // check correctness for the variable names and types within the expression + for (auto var_name : var_list) + { + auto itVariable = m_Variables.find(var_name); + if (itVariable == m_Variables.end()) + helper::Throw("Core", "IO", "DefineDerivedVariable", + "using undefine variable " + var_name + + " in defining the derived variable " + name); + DataType var_type = InquireVariableType(var_name); + if (expressionType == DataType::None) + expressionType = var_type; + if (expressionType != var_type) + helper::Throw("Core", "IO", "DefineDerivedVariable", + "all variables within a derived variable " + " must have the same type "); + if ((itVariable->second)->IsConstantDims() == false) + isConstant = false; + name_to_dims.insert({var_name, + {(itVariable->second)->m_Start, (itVariable->second)->m_Count, + (itVariable->second)->m_Shape}}); + } + // std::cout << "Derived variable " << name << ": PASS : variables exist and have the same type" + // << std::endl; + // set the initial shape of the expression and check correcness + derived_exp.SetDims(name_to_dims); + // std::cout << "Derived variable " << name << ": PASS : initial variable dimensions are valid" + // << std::endl; + + // create derived variable with the expression + auto itVariablePair = m_VariablesDerived.emplace( + name, std::unique_ptr( + new VariableDerived(name, derived_exp, expressionType, isConstant, varType))); + VariableDerived &variable = static_cast(*itVariablePair.first->second); + + // check IO placeholder for variable operations + auto itOperations = m_VarOpsPlaceholder.find(name); + if (itOperations != m_VarOpsPlaceholder.end()) + { + // allow to apply an operation only for derived variables that save the data + if (varType != DerivedVarType::StoreData) + helper::Throw( + "Core", "IO", "DefineDerivedVariable", + "Operators for derived variables can only be applied " + " for DerivedVarType::StoreData types."); + variable.m_Operations.reserve(itOperations->second.size()); + for (auto &operation : itOperations->second) + { + variable.AddOperation(operation.first, operation.second); + } + } + return variable; +} +#endif + StructDefinition &IO::DefineStruct(const std::string &name, const size_t size) { return m_ADIOS.m_StructDefinitions.emplace(name, StructDefinition(name, size))->second; diff --git a/source/adios2/core/IO.h b/source/adios2/core/IO.h index 4d64982f3b..0bdf279d12 100644 --- a/source/adios2/core/IO.h +++ b/source/adios2/core/IO.h @@ -28,6 +28,9 @@ #include "adios2/core/CoreTypes.h" #include "adios2/core/Group.h" #include "adios2/core/Variable.h" +#ifdef ADIOS2_HAVE_DERIVED_VARIABLE +#include "adios2/core/VariableDerived.h" +#endif #include "adios2/core/VariableStruct.h" namespace adios2 @@ -179,7 +182,11 @@ class IO Variable &DefineVariable(const std::string &name, const Dims &shape = Dims(), const Dims &start = Dims(), const Dims &count = Dims(), const bool constantDims = false); - +#ifdef ADIOS2_HAVE_DERIVED_VARIABLE + VariableDerived & + DefineDerivedVariable(const std::string &name, const std::string &expression, + const DerivedVarType varType = DerivedVarType::MetadataOnly); +#endif VariableStruct &DefineStructVariable(const std::string &name, StructDefinition &def, const Dims &shape = Dims(), const Dims &start = Dims(), const Dims &count = Dims(), @@ -304,6 +311,9 @@ class IO * */ const VarMap &GetVariables() const noexcept; +#ifdef ADIOS2_HAVE_DERIVED_VARIABLE + const VarMap &GetDerivedVariables() const noexcept; +#endif /** * Retrieves hash holding internal Attributes identifiers @@ -500,6 +510,9 @@ class IO adios2::IOMode m_IOMode = adios2::IOMode::Independent; VarMap m_Variables; +#ifdef ADIOS2_HAVE_DERIVED_VARIABLE + VarMap m_VariablesDerived; +#endif AttrMap m_Attributes; diff --git a/source/adios2/core/VariableDerived.cpp b/source/adios2/core/VariableDerived.cpp new file mode 100644 index 0000000000..670ad0bc35 --- /dev/null +++ b/source/adios2/core/VariableDerived.cpp @@ -0,0 +1,121 @@ +#include "VariableDerived.h" +#include "adios2/helper/adiosType.h" + +namespace adios2 +{ +namespace core +{ + +VariableDerived::VariableDerived(const std::string &name, adios2::derived::Expression expr, + const DataType exprType, const bool isConstant, + const DerivedVarType varType) +: VariableBase(name, exprType, helper::GetDataTypeSize(exprType), expr.GetShape(), expr.GetStart(), + expr.GetCount(), isConstant), + m_Expr(expr), m_DerivedType(varType) +{ +} + +DerivedVarType VariableDerived::GetDerivedType() { return m_DerivedType; } + +std::vector VariableDerived::VariableNameList() { return m_Expr.VariableNameList(); } +void VariableDerived::UpdateExprDim(std::map> NameToDims) +{ + m_Expr.SetDims(NameToDims); + m_Shape = m_Expr.GetShape(); + m_Start = m_Expr.GetStart(); + m_Count = m_Expr.GetCount(); +} + +std::vector> +VariableDerived::ApplyExpression(std::map NameToMVI) +{ + size_t numBlocks = 0; + // check that all variables have the same number of blocks + for (auto variable : NameToMVI) + { + if (numBlocks == 0) + numBlocks = variable.second.BlocksInfo.size(); + if (numBlocks != variable.second.BlocksInfo.size()) + helper::Throw("Core", "VariableDerived", "ApplyExpression", + " variables do not have the same number of blocks " + " in computing the derived variable " + + m_Name); + } + + std::map> inputData; + // create the map between variable name and DerivedData object + for (auto variable : NameToMVI) + { + // add the dimensions of all blocks into a vector + std::vector varData; + for (size_t i = 0; i < numBlocks; i++) + { + Dims start; + Dims count; + for (size_t d = 0; d < variable.second.Dims; d++) + { + start.push_back(variable.second.BlocksInfo[i].Start[d]); + count.push_back(variable.second.BlocksInfo[i].Count[d]); + } + varData.push_back(adios2::derived::DerivedData( + {variable.second.BlocksInfo[i].BufferP, start, count})); + } + inputData.insert({variable.first, varData}); + } + // TODO check that the dimensions are still corrects + std::vector outputData = + m_Expr.ApplyExpression(m_Type, numBlocks, inputData); + + std::vector> blockData; + for (size_t i = 0; i < numBlocks; i++) + { + blockData.push_back({outputData[i].Data, outputData[i].Start, outputData[i].Count}); + } + + return blockData; +} + +std::vector +VariableDerived::ApplyExpression(std::map> NameToData, + std::map> NameToDims) +{ + size_t numBlocks = 0; + std::map> inputData; + // check that all variables have the same number of blocks + for (auto variable : NameToData) + { + if (numBlocks == 0) + numBlocks = variable.second.size(); + if (numBlocks != variable.second.size()) + helper::Throw("Core", "VariableDerived", "ApplyExpression", + " variables do not have the same number of blocks " + " in computing the derived variable " + + m_Name); + } + std::cout << "Derived variable " << m_Name + << ": PASS : variables have written the same num of blocks" << std::endl; + // create the map between variable name and DerivedData object + for (auto variable : NameToData) + { + // add the dimensions of all blocks into a vector + std::vector varData; + for (size_t i = 0; i < numBlocks; i++) + { + varData.push_back(adios2::derived::DerivedData( + {variable.second[i], std::get<0>(NameToDims[variable.first]), + std::get<1>(NameToDims[variable.first])})); + } + inputData.insert({variable.first, varData}); + } + std::vector outputData = + m_Expr.ApplyExpression(m_Type, numBlocks, inputData); + std::vector blockData; + for (size_t i = 0; i < numBlocks; i++) + { + blockData.push_back(outputData[i].Data); + } + return blockData; +} + +} // end namespace core +} // end namespace adios2 diff --git a/source/adios2/core/VariableDerived.h b/source/adios2/core/VariableDerived.h new file mode 100644 index 0000000000..2ff9eb3903 --- /dev/null +++ b/source/adios2/core/VariableDerived.h @@ -0,0 +1,41 @@ +#ifndef ADIOS2_CORE_VARIABLE_DERIVED_H_ +#define ADIOS2_CORE_VARIABLE_DERIVED_H_ + +#include "adios2/common/ADIOSTypes.h" +#include "adios2/core/VariableBase.h" +#include "adios2/helper/adiosType.h" +#include "adios2/toolkit/derived/Expression.h" + +namespace adios2 +{ +namespace core +{ + +/** + * @param Base (parent) class for template derived (child) class Variable. + */ +class VariableDerived : public VariableBase +{ + DerivedVarType m_DerivedType; + +public: + adios2::derived::Expression m_Expr; + VariableDerived(const std::string &name, adios2::derived::Expression expr, + const DataType exprType, const bool isConstant, const DerivedVarType varType); + ~VariableDerived() = default; + + DerivedVarType GetDerivedType(); + std::vector VariableNameList(); + void UpdateExprDim(std::map> NameToDims); + + std::vector + ApplyExpression(std::map> NameToData, + std::map> NameToDims); + std::vector> + ApplyExpression(std::map mvi); +}; + +} // end namespace core +} // end namespace adios2 + +#endif /* ADIOS2_CORE_VARIABLE_DERIVED_H_ */ diff --git a/source/adios2/engine/bp5/BP5Writer.cpp b/source/adios2/engine/bp5/BP5Writer.cpp index 465a44d959..9ae651fc3a 100644 --- a/source/adios2/engine/bp5/BP5Writer.cpp +++ b/source/adios2/engine/bp5/BP5Writer.cpp @@ -495,8 +495,72 @@ void BP5Writer::MarshalAttributes() } } +#ifdef ADIOS2_HAVE_DERIVED_VARIABLE +void BP5Writer::ComputeDerivedVariables() +{ + auto const &m_VariablesDerived = m_IO.GetDerivedVariables(); + auto const &m_Variables = m_IO.GetVariables(); + // parse all derived variables + for (auto it = m_VariablesDerived.begin(); it != m_VariablesDerived.end(); it++) + { + // identify the variables used in the derived variable + auto derivedVar = dynamic_cast((*it).second.get()); + std::vector varList = derivedVar->VariableNameList(); + // to create a mapping between variable name and the varInfo (dim and data pointer) + std::map nameToVarInfo; + bool computeDerived = true; + for (auto varName : varList) + { + auto itVariable = m_Variables.find(varName); + if (itVariable == m_Variables.end()) + helper::Throw("Core", "IO", "DefineDerivedVariable", + "using undefine variable " + varName + + " in defining the derived variable " + + (*it).second->m_Name); + // extract the dimensions and data for each variable + VariableBase *varBase = itVariable->second.get(); + auto mvi = WriterMinBlocksInfo(*varBase); + if (mvi->BlocksInfo.size() == 0) + { + computeDerived = false; + std::cout << "Variable " << itVariable->first << " not written in this step"; + std::cout << " .. skip derived variable " << (*it).second->m_Name << std::endl; + break; + } + nameToVarInfo.insert({varName, *mvi}); + } + // skip computing derived variables if it contains variables that are not written this step + if (!computeDerived) + continue; + + // compute the values for the derived variables that are not type ExpressionString + std::vector> DerivedBlockData; + if (derivedVar->GetDerivedType() != DerivedVarType::ExpressionString) + { + DerivedBlockData = derivedVar->ApplyExpression(nameToVarInfo); + } + + // Send the derived variable to ADIOS2 internal logic + for (auto derivedBlock : DerivedBlockData) + { + // set the shape of the variable for each block + if (!(*it).second->IsConstantDims()) + { + (*it).second->m_Start = std::get<1>(derivedBlock); + (*it).second->m_Count = std::get<2>(derivedBlock); + } + PutCommon(*(*it).second.get(), std::get<0>(derivedBlock), true /* sync */); + free(std::get<0>(derivedBlock)); + } + } +} +#endif + void BP5Writer::EndStep() { +#ifdef ADIOS2_HAVE_DERIVED_VARIABLE + ComputeDerivedVariables(); +#endif m_BetweenStepPairs = false; PERFSTUBS_SCOPED_TIMER("BP5Writer::EndStep"); m_Profiler.Start("ES"); @@ -504,26 +568,6 @@ void BP5Writer::EndStep() m_Profiler.Start("ES_close"); MarshalAttributes(); -#ifdef NOT_DEF - const auto &vars = m_IO.GetVariables(); - for (const auto &varPair : vars) - { - auto baseVar = varPair.second.get(); - auto mvi = WriterMinBlocksInfo(*baseVar); - if (mvi) - { - std::cout << "Info for Variable " << varPair.first << std::endl; - PrintMVI(std::cout, *mvi); - if (baseVar->m_Type == DataType::Double) - std::cout << "Double value is " << *((double *)mvi->BlocksInfo[0].BufferP) - << std::endl; - delete mvi; - } - else - std::cout << "Variable " << varPair.first << " not written on this step" << std::endl; - } -#endif - // true: advances step auto TSInfo = m_BP5Serializer.CloseTimestep((int)m_WriterStep, m_Parameters.AsyncWrite || m_Parameters.DirectIO); diff --git a/source/adios2/engine/bp5/BP5Writer.h b/source/adios2/engine/bp5/BP5Writer.h index eaddf93b9d..cfaeb51bf2 100644 --- a/source/adios2/engine/bp5/BP5Writer.h +++ b/source/adios2/engine/bp5/BP5Writer.h @@ -119,6 +119,10 @@ class BP5Writer : public BP5Engine, public core::Engine /** Inform about computation block through User->ADIOS->IO */ void ExitComputationBlock() noexcept; +#ifdef ADIOS2_HAVE_DERIVED_VARIABLE + void ComputeDerivedVariables(); +#endif + #define declare_type(T) \ void DoPut(Variable &variable, typename Variable::Span &span, const bool initialize, \ const T &value) final; diff --git a/source/adios2/toolkit/derived/ExprHelper.h b/source/adios2/toolkit/derived/ExprHelper.h new file mode 100644 index 0000000000..c72888f95f --- /dev/null +++ b/source/adios2/toolkit/derived/ExprHelper.h @@ -0,0 +1,60 @@ +#ifndef ADIOS2_DERIVED_PARSER_EXPHELPER_H_ +#define ADIOS2_DERIVED_PARSER_EXPHELPER_H_ + +#include +#include +#include +#include + +namespace adios2 +{ +namespace detail +{ + +enum ExpressionOperator +{ + OP_NULL, + OP_ALIAS, /* Parser-use only */ + OP_PATH, /* Parser-use only */ + OP_NUM, /* Parser-use only */ + OP_INDEX, + OP_ADD, + OP_SQRT, + OP_POW, + OP_MAGN +}; + +struct OperatorProperty +{ + std::string name; + bool is_associative; +}; + +const std::map op_property = { + {ExpressionOperator::OP_NULL, {"NULL", false}}, + {ExpressionOperator::OP_ALIAS, {"ALIAS", false}}, /* Parser-use only */ + {ExpressionOperator::OP_PATH, {"PATH", false}}, /* Parser-use only */ + {ExpressionOperator::OP_NUM, {"NUM", false}}, /* Parser-use only */ + {ExpressionOperator::OP_INDEX, {"INDEX", false}}, + {ExpressionOperator::OP_ADD, {"ADD", true}}, + {ExpressionOperator::OP_SQRT, {"SQRT", false}}, + {ExpressionOperator::OP_POW, {"POW", false}}, + {ExpressionOperator::OP_MAGN, {"MAGNITUDE", false}}}; + +const std::map string_to_op = { + {"ALIAS", ExpressionOperator::OP_ALIAS}, /* Parser-use only */ + {"PATH", ExpressionOperator::OP_PATH}, /* Parser-use only */ + {"NUM", ExpressionOperator::OP_NUM}, /* Parser-use only */ + {"INDEX", ExpressionOperator::OP_INDEX}, {"+", ExpressionOperator::OP_ADD}, + {"add", ExpressionOperator::OP_ADD}, {"ADD", ExpressionOperator::OP_ADD}, + {"SQRT", ExpressionOperator::OP_SQRT}, {"sqrt", ExpressionOperator::OP_SQRT}, + {"POW", ExpressionOperator::OP_POW}, {"^", ExpressionOperator::OP_POW}, + {"MAGNITUDE", ExpressionOperator::OP_MAGN}, {"magnitude", ExpressionOperator::OP_MAGN}}; + +inline std::string get_op_name(ExpressionOperator op) { return op_property.at(op).name; } + +inline ExpressionOperator get_op(std::string op) { return string_to_op.at(op); } + +} +} +#endif \ No newline at end of file diff --git a/source/adios2/toolkit/derived/Expression.cpp b/source/adios2/toolkit/derived/Expression.cpp new file mode 100644 index 0000000000..d773236526 --- /dev/null +++ b/source/adios2/toolkit/derived/Expression.cpp @@ -0,0 +1,226 @@ +#ifndef ADIOS2_DERIVED_Expression_CPP_ +#define ADIOS2_DERIVED_Expression_CPP_ + +#include "Expression.h" +#include "parser/ASTNode.h" +#include "parser/parser.h" + +namespace adios2 +{ +namespace detail +{ +adios2::derived::ExpressionTree ASTNode_to_ExpressionTree(adios2::detail::ASTNode *node) +{ + adios2::derived::ExpressionTree exprTree_node(node->operation); + for (adios2::detail::ASTNode *e : node->sub_expr) + { + switch (e->operation) + { + case adios2::detail::ExpressionOperator::OP_ALIAS: // add variable given by alias + // add an index operation in the chain if the variable contains indeces + /*if (e->lookup_var_indices(e->alias) != "") + { + ExpressionTree index_expr(adios2::detail::ExpressionOperator::OP_INDEX); + index_expr.set_indeces(e->lookup_var_indices(e->alias)); + index_expr.add_child(e->lookup_var_path(e->alias)); + expTree_node->add_child(expr); + }*/ + exprTree_node.add_child(e->lookup_var_path(e->alias)); + break; + case adios2::detail::ExpressionOperator::OP_PATH: // add variable name + exprTree_node.add_child(e->alias); + break; + case adios2::detail::ExpressionOperator::OP_NUM: // set the base value for the operation + exprTree_node.set_base(e->value); + break; + default: // if the children nodes are other expressions, convert them to expressions + auto temp_node = ASTNode_to_ExpressionTree(e); + // move from a binary to a multinary tree if the child has the same operation + if (e->operation == node->operation && + adios2::detail::op_property.at(e->operation).is_associative) + { + // concatenate exprTree with temp_node + for (std::tuple childTree : + temp_node.sub_exprs) + { + if (std::get<2>(childTree) == true) + exprTree_node.add_child(std::get<0>(childTree)); + else + exprTree_node.add_child(std::get<1>(childTree)); + } + } + else + { + exprTree_node.add_child(temp_node); + } + } + } + return exprTree_node; +} +} + +namespace derived +{ + +Expression::Expression(std::string string_exp) +: ExprString(string_exp), m_Shape({0}), m_Start({0}), m_Count({0}) +{ + adios2::detail::ASTNode *root_node = adios2::detail::parse_expression(string_exp); + m_Expr = adios2::detail::ASTNode_to_ExpressionTree(root_node); +} + +std::vector Expression::VariableNameList() { return m_Expr.VariableNameList(); } + +Dims Expression::GetShape() { return m_Shape; } + +Dims Expression::GetStart() { return m_Start; } + +Dims Expression::GetCount() { return m_Count; } + +void Expression::SetDims(std::map> NameToDims) +{ + std::map NameToCount, NameToStart, NameToShape; + for (const auto &it : NameToDims) + { + NameToStart[it.first] = std::get<0>(it.second); + NameToCount[it.first] = std::get<1>(it.second); + NameToShape[it.first] = std::get<2>(it.second); + } + m_Count = m_Expr.GetDims(NameToCount); + m_Start = m_Expr.GetDims(NameToStart); + m_Shape = m_Expr.GetDims(NameToShape); +} + +std::vector +Expression::ApplyExpression(DataType type, size_t numBlocks, + std::map> nameToData) +{ + return m_Expr.ApplyExpression(type, numBlocks, nameToData); +} + +void ExpressionTree::set_base(double c) { detail.constant = c; } + +void ExpressionTree::set_indeces(std::vector> index_list) +{ + detail.indices = index_list; +} + +void ExpressionTree::add_child(ExpressionTree exp) { sub_exprs.push_back({exp, "", true}); } + +void ExpressionTree::add_child(std::string var) +{ + sub_exprs.push_back({ExpressionTree(), var, false}); +} + +std::vector ExpressionTree::VariableNameList() +{ + std::vector var_list; + for (auto subexp : sub_exprs) + { + // if the sub_expression is a leaf + if (!std::get<2>(subexp)) + { + var_list.push_back(std::get<1>(subexp)); + } + else + { + auto subexpr_list = std::get<0>(subexp).VariableNameList(); + var_list.insert(var_list.end(), subexpr_list.begin(), subexpr_list.end()); + } + } + return var_list; +} + +void ExpressionTree::print() +{ + std::cout << "Print Expression:" << std::endl; + std::cout << "\toperation: " << get_op_name(detail.operation) << std::endl; + std::cout << "\tconstant: " << detail.constant << std::endl; + std::cout << "\tchildren: " << sub_exprs.size() << std::endl; + + for (std::tuple t : sub_exprs) + { + if (std::get<2>(t) == true) + { + std::get<0>(t).print(); + } + else + { + std::cout << "string: " << std::get<1>(t) << std::endl; + } + } +} + +Dims ExpressionTree::GetDims(std::map NameToDims) +{ + std::vector exprDims; + for (auto subexp : sub_exprs) + { + // if the sub_expression is a leaf, we get the shape from the input std::map + if (!std::get<2>(subexp)) + { + exprDims.push_back(NameToDims[std::get<1>(subexp)]); + } + else + { + exprDims.push_back(std::get<0>(subexp).GetDims(NameToDims)); + } + } + // get the output dimensions after applying the operator + auto op_fct = OpFunctions.at(detail.operation); + Dims opDims = op_fct.DimsFct(exprDims); + return opDims; +} + +std::vector +ExpressionTree::ApplyExpression(DataType type, size_t numBlocks, + std::map> nameToData) +{ + // create operands for the computation function + // exprData[0] = list of void* data for block 0 for each variable + std::vector> exprData(numBlocks); + std::vector dealocate; + for (auto subexp : sub_exprs) + { + if (!std::get<2>(subexp)) + { + // do not dealocate leafs (this is user data) + dealocate.push_back(false); + for (size_t blk = 0; blk < numBlocks; blk++) + { + exprData[blk].push_back(nameToData[std::get<1>(subexp)][blk]); + } + } + else + { + dealocate.push_back(true); + auto subexpData = std::get<0>(subexp).ApplyExpression(type, numBlocks, nameToData); + for (size_t blk = 0; blk < numBlocks; blk++) + { + exprData[blk].push_back(subexpData[blk]); + } + } + } + // apply the computation operator on all blocks + std::vector outputData(numBlocks); + auto op_fct = OpFunctions.at(detail.operation); + for (size_t blk = 0; blk < numBlocks; blk++) + { + outputData[blk] = op_fct.ComputeFct(exprData[blk], type); + } + // deallocate intermediate data after computing the operation + for (size_t blk = 0; blk < numBlocks; blk++) + { + for (size_t i = 0; i < exprData[blk].size(); i++) + { + if (dealocate[i] == false) + continue; + free(exprData[blk][i].Data); + } + } + return outputData; +} + +} +} +#endif diff --git a/source/adios2/toolkit/derived/Expression.h b/source/adios2/toolkit/derived/Expression.h new file mode 100644 index 0000000000..6f60f1c262 --- /dev/null +++ b/source/adios2/toolkit/derived/Expression.h @@ -0,0 +1,85 @@ +#ifndef ADIOS2_DERIVED_Expression_H_ +#define ADIOS2_DERIVED_Expression_H_ + +#include "Function.h" +#include "adios2/common/ADIOSTypes.h" +#include +#include + +namespace adios2 +{ + +namespace derived +{ +/* + A Note on ExpressionTree: + - Sub expressions can include another operation node or a variable name + - the third entry in the tuple distinguishes between variable and operation + - OpInfo contains information about the operation stoder in the node + - The type of the operation + - Indexing/Slicing: detail is indices (std::vector>, e.g. for each dimension start:end:stride + - Constant used to compute the operation [e.g. log_2] + */ +struct OpInfo +{ + adios2::detail::ExpressionOperator operation; + std::vector> indices; + double constant; +}; + +class ExpressionTree +{ +public: + std::vector> sub_exprs; + OpInfo detail; + + ExpressionTree(){}; + ExpressionTree(adios2::detail::ExpressionOperator o) : detail({o, {}, 0}) {} + ExpressionTree(adios2::detail::ExpressionOperator o, double c) : detail({o, {}, 0}) {} + ExpressionTree(std::vector> indices) + : detail({adios2::detail::ExpressionOperator ::OP_INDEX, indices, 0}) + { + } + + void set_base(double c); + void set_indeces(std::vector> index_list); + + void add_child(ExpressionTree exp); + void add_child(std::string var); + + std::vector VariableNameList(); + Dims GetDims(std::map NameToDims); + std::vector + ApplyExpression(DataType type, size_t numBlocks, + std::map> nameToData); + void print(); +}; + +class Expression +{ + ExpressionTree m_Expr; + + Dims m_Shape; + Dims m_Start; + Dims m_Count; + +public: + Expression() = default; + Expression(std::string expression); + + std::string ExprString; + + Dims GetShape(); + Dims GetStart(); + Dims GetCount(); + void SetDims(std::map> NameToDims); + std::vector VariableNameList(); + std::vector + ApplyExpression(DataType type, size_t numBlocks, + std::map> nameToData); +}; + +} +} +#endif diff --git a/source/adios2/toolkit/derived/Function.cpp b/source/adios2/toolkit/derived/Function.cpp new file mode 100644 index 0000000000..c524ac8c15 --- /dev/null +++ b/source/adios2/toolkit/derived/Function.cpp @@ -0,0 +1,74 @@ +#ifndef ADIOS2_DERIVED_Function_CPP_ +#define ADIOS2_DERIVED_Function_CPP_ + +#include "Function.h" +#include "Function.tcc" +#include "adios2/common/ADIOSMacros.h" +#include "adios2/helper/adiosFunctions.h" +#include + +namespace adios2 +{ +namespace derived +{ + +DerivedData AddFunc(std::vector inputData, DataType type) +{ + size_t dataSize = std::accumulate(std::begin(inputData[0].Count), std::end(inputData[0].Count), + 1, std::multiplies()); + +#define declare_type_add(T) \ + if (type == helper::GetDataType()) \ + { \ + T *addValues = ApplyOneToOne(inputData, dataSize, [](T a, T b) { return a + b; }); \ + return DerivedData({(void *)addValues, inputData[0].Start, inputData[0].Count}); \ + } + ADIOS2_FOREACH_PRIMITIVE_STDTYPE_1ARG(declare_type_add) + helper::Throw("Derived", "Function", "AddFunc", + "Invalid variable types"); + return DerivedData(); +} + +DerivedData MagnitudeFunc(std::vector inputData, DataType type) +{ + size_t dataSize = std::accumulate(std::begin(inputData[0].Count), std::end(inputData[0].Count), + 1, std::multiplies()); +#define declare_type_mag(T) \ + if (type == helper::GetDataType()) \ + { \ + T *magValues = ApplyOneToOne(inputData, dataSize, [](T a, T b) { return a + b * b; }); \ + for (size_t i = 0; i < dataSize; i++) \ + { \ + magValues[i] = std::sqrt(magValues[i]); \ + } \ + return DerivedData({(void *)magValues, inputData[0].Start, inputData[0].Count}); \ + } + ADIOS2_FOREACH_PRIMITIVE_STDTYPE_1ARG(declare_type_mag) + helper::Throw("Derived", "Function", "MagnitudeFunc", + "Invalid variable types"); + return DerivedData(); +} + +Dims SameDimsFunc(std::vector input) +{ + // check that all dimenstions are the same + if (input.size() > 1) + { + bool dim_are_equal = std::equal(input.begin() + 1, input.end(), input.begin()); + if (!dim_are_equal) + helper::Throw("Derived", "Function", "SameDimFunc", + "Invalid variable dimensions"); + } + // return the first dimension + return input[0]; +} + +#define declare_template_instantiation(T) \ + T *ApplyOneToOne(std::vector, size_t, std::function); + +ADIOS2_FOREACH_PRIMITIVE_STDTYPE_1ARG(declare_template_instantiation) +#undef declare_template_instantiation + +} +} // namespace adios2 +#endif diff --git a/source/adios2/toolkit/derived/Function.h b/source/adios2/toolkit/derived/Function.h new file mode 100644 index 0000000000..5dfa5aba97 --- /dev/null +++ b/source/adios2/toolkit/derived/Function.h @@ -0,0 +1,42 @@ +#ifndef ADIOS2_DERIVED_Function_H_ +#define ADIOS2_DERIVED_Function_H_ + +#include "ExprHelper.h" +#include "adios2/common/ADIOSTypes.h" +#include "adios2/helper/adiosLog.h" +#include + +namespace adios2 +{ +namespace derived +{ + +struct DerivedData +{ + void *Data; + Dims Start; + Dims Count; +}; + +struct OperatorFunctions +{ + std::function, DataType)> ComputeFct; + std::function)> DimsFct; +}; + +DerivedData AddFunc(std::vector input, DataType type); +DerivedData MagnitudeFunc(std::vector input, DataType type); + +Dims SameDimsFunc(std::vector input); + +const std::map OpFunctions = { + {adios2::detail::ExpressionOperator::OP_ADD, {AddFunc, SameDimsFunc}}, + {adios2::detail::ExpressionOperator::OP_MAGN, {MagnitudeFunc, SameDimsFunc}}}; + +template +T *ApplyOneToOne(std::vector inputData, size_t dataSize, + std::function compFct); + +} +} +#endif diff --git a/source/adios2/toolkit/derived/Function.tcc b/source/adios2/toolkit/derived/Function.tcc new file mode 100644 index 0000000000..1c47c1665b --- /dev/null +++ b/source/adios2/toolkit/derived/Function.tcc @@ -0,0 +1,39 @@ +#ifndef ADIOS2_DERIVED_Function_TCC_ +#define ADIOS2_DERIVED_Function_TCC_ + +#include "Function.h" +#include +#include +#include +#include + +namespace adios2 +{ +namespace derived +{ + +template +T *ApplyOneToOne(std::vector inputData, size_t dataSize, + std::function compFct) +{ + T *outValues = (T *)malloc(dataSize * sizeof(T)); + if (outValues == nullptr) + { + std::cout << "Allocation failed for the derived data" << std::endl; + // TODO - throw an exception + } + memset(outValues, 0, dataSize * sizeof(T)); + for (auto &variable : inputData) + { + for (size_t i = 0; i < dataSize; i++) + { + T data = *(reinterpret_cast(variable.Data) + i); + outValues[i] = compFct(outValues[i], data); + } + } + return outValues; +} + +} +} +#endif diff --git a/source/adios2/toolkit/derived/parser/ASTNode.cpp b/source/adios2/toolkit/derived/parser/ASTNode.cpp new file mode 100644 index 0000000000..5cbc07322d --- /dev/null +++ b/source/adios2/toolkit/derived/parser/ASTNode.cpp @@ -0,0 +1,143 @@ +#ifndef ADIOS2_DERIVED_PARSER_ASTNODE_CPP_ +#define ADIOS2_DERIVED_PARSER_ASTNODE_CPP_ + +#include "ASTNode.h" + +namespace adios2 +{ +namespace detail +{ + +/*****************************************/ +// alias maps to pair of path and indices (indices may be empty string) +std::map> ASTNode::var_lookup; + +ASTNode::ASTNode() {} + +ASTNode::ASTNode(ExpressionOperator op) : operation(op) {} + +ASTNode::ASTNode(ExpressionOperator op, const char *str) : operation(op) +{ + switch (operation) + { + case ExpressionOperator::OP_ALIAS: + alias = str; + break; + case ExpressionOperator::OP_PATH: + alias = str; + break; + case ExpressionOperator::OP_INDEX: + indices = str; + break; + default: + // TODO: Make some error + // std::cout << "***That's a problem... ASTNode constructed with string should be alias + // type, path type, or index type\n"; + break; + } +} + +ASTNode::ASTNode(ExpressionOperator op, double val) : operation(op), value(val) {} + +ASTNode::ASTNode(ExpressionOperator op, ASTNode *e) : operation(op) { sub_expr.push_back(e); } + +// for index +ASTNode::ASTNode(ExpressionOperator op, ASTNode *e, const char *str) : operation(op), indices(str) +{ + sub_expr.push_back(e); +} + +ASTNode::ASTNode(ExpressionOperator op, ASTNode *e1, ASTNode *e2) : operation(op) +{ + sub_expr.push_back(e1); + sub_expr.push_back(e2); +} + +// Copy constructor +ASTNode::ASTNode(const ASTNode &e) +: operation(e.operation), alias(e.alias), value(e.value), sub_expr(e.sub_expr) +{ +} + +ASTNode::~ASTNode() +{ + for (ASTNode *e : sub_expr) + { + delete e; + } +} + +std::pair ASTNode::lookup_var(const std::string var_alias) +{ + return var_lookup[var_alias]; +} + +std::string ASTNode::lookup_var_path(const std::string var_alias) +{ + return var_lookup[var_alias].first; +} + +std::string ASTNode::lookup_var_indices(const std::string var_alias) +{ + return var_lookup[var_alias].second; +} + +void ASTNode::add_lookup_entry(const std::string alias, const std::string var_name, + const std::string indices) +{ + // std::cout << "Adding alias to lookup table:\n\talias: " << alias << "\n\tvar_name: " << + // var_name << "\n\tindices: " << indices << std::endl; + var_lookup[alias] = std::make_pair(var_name, indices); +} + +void ASTNode::add_subexpr(ASTNode *e) { sub_expr.push_back(e); } + +void ASTNode::add_back_subexpr(ASTNode *e, size_t n) +{ + size_t index = sub_expr.size() - n; + // std::cout << "ASTNode add_back_subexpr index: " << index << std::endl; + // if (index > 0 && sub_expr[index] == nullptr) + sub_expr[index] = e; +} + +void ASTNode::extend_subexprs(size_t n) +{ + // std::cout << "ASTNode extending subexprs from size " << sub_expr.size() << " to " << + // (sub_expr.size() + n) << std::endl; + sub_expr.resize(sub_expr.size() + n); +} + +void ASTNode::printpretty(std::string indent) +{ + std::cout << indent << get_op_name(operation) << ":"; + if (operation == ExpressionOperator::OP_ALIAS) + { + std::cout << " (alias " << alias << " maps to Variable '"; + std::cout << lookup_var_path(alias) << "'"; + if (lookup_var_indices(alias) != "") + { + std::cout << " [" << lookup_var_indices(alias) << "]"; + } + std::cout << ")"; + } + else if (operation == ExpressionOperator::OP_PATH) + { + std::cout << " (" << alias << ")"; + } + else if (operation == ExpressionOperator::OP_INDEX) + { + std::cout << " [" << indices << "]"; + } + std::cout << std::endl; + for (ASTNode *e : sub_expr) + { + if (e != nullptr) + e->printpretty(indent + " "); + else + std::cout << "sub_expr is nullptr" << std::endl; + } +} + +} +} +#endif diff --git a/source/adios2/toolkit/derived/parser/ASTNode.h b/source/adios2/toolkit/derived/parser/ASTNode.h new file mode 100644 index 0000000000..72cec1a812 --- /dev/null +++ b/source/adios2/toolkit/derived/parser/ASTNode.h @@ -0,0 +1,58 @@ +#ifndef ADIOS2_DERIVED_PARSER_ASTNODE_H_ +#define ADIOS2_DERIVED_PARSER_ASTNODE_H_ + +#include +#include +#include +#include + +#include "../ExprHelper.h" + +/*****************************************/ + +namespace adios2 +{ +namespace detail +{ + +class ASTNode +{ +public: + ASTNode(); + ASTNode(ExpressionOperator); + ASTNode(ExpressionOperator, const char *a); + ASTNode(ExpressionOperator, double val); + ASTNode(ExpressionOperator, ASTNode *e); + ASTNode(ExpressionOperator, ASTNode *e, const char *i); + ASTNode(ExpressionOperator, ASTNode *e1, ASTNode *e2); + + // Copy constructor + ASTNode(const ASTNode &e); + + ~ASTNode(); + + static std::pair lookup_var(const std::string var_alias); + static std::string lookup_var_path(const std::string var_alias); + static std::string lookup_var_indices(const std::string var_alias); + static void add_lookup_entry(const std::string alias, const std::string var_name, + const std::string indices); + + void add_subexpr(ASTNode *e); + void add_back_subexpr(ASTNode *e, size_t i); + void extend_subexprs(size_t n); + void infer_type(); + void printpretty(std::string indent = ""); + + // private: + ExpressionOperator operation; + std::string alias; + std::string indices; + double value; + std::vector sub_expr; + + static std::map> var_lookup; +}; + +} +} +#endif \ No newline at end of file diff --git a/source/adios2/toolkit/derived/parser/lexer.cpp b/source/adios2/toolkit/derived/parser/lexer.cpp new file mode 100644 index 0000000000..03b101c191 --- /dev/null +++ b/source/adios2/toolkit/derived/parser/lexer.cpp @@ -0,0 +1,1884 @@ +#line 1 "lexer.cpp" + +#line 3 "lexer.cpp" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 6 +#define YY_FLEX_SUBMINOR_VERSION 4 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +typedef uint64_t flex_uint64_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767 - 1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647 - 1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#ifndef SIZE_MAX +#define SIZE_MAX (~(size_t)0) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +/* begin standard C++ headers. */ + +/* TODO: this is always defined, so inline it */ +#define yyconst const + +#if defined(__GNUC__) && __GNUC__ >= 3 +#define yynoreturn __attribute__((__noreturn__)) +#else +#define yynoreturn +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an + * integer in range [0..255] for use as an array index. + */ +#define YY_SC_TO_UI(c) ((YY_CHAR)(c)) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start)-1) / 2) +#define YYSTATE YY_START +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart(yyin) +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +extern yy_size_t yyleng; + +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +#define YY_LESS_LINENO(n) +#define YY_LINENO_REWIND_TO(ptr) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg); \ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } while (0) +#define unput(c) yyunput(c, (yytext_ptr)) + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state +{ + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + int yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + yy_size_t yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 +}; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE *yy_buffer_stack = NULL; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ((yy_buffer_stack) ? (yy_buffer_stack)[(yy_buffer_stack_top)] : NULL) +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; +static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */ +yy_size_t yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = NULL; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart(FILE *input_file); +void yy_switch_to_buffer(YY_BUFFER_STATE new_buffer); +YY_BUFFER_STATE yy_create_buffer(FILE *file, int size); +void yy_delete_buffer(YY_BUFFER_STATE b); +void yy_flush_buffer(YY_BUFFER_STATE b); +void yypush_buffer_state(YY_BUFFER_STATE new_buffer); +void yypop_buffer_state(void); + +static void yyensure_buffer_stack(void); +static void yy_load_buffer_state(void); +static void yy_init_buffer(YY_BUFFER_STATE b, FILE *file); +#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER) + +YY_BUFFER_STATE yy_scan_buffer(char *base, yy_size_t size); +YY_BUFFER_STATE yy_scan_string(const char *yy_str); +YY_BUFFER_STATE yy_scan_bytes(const char *bytes, yy_size_t len); + +void *yyalloc(yy_size_t); +void *yyrealloc(void *, yy_size_t); +void yyfree(void *); + +#define yy_new_buffer yy_create_buffer +#define yy_set_interactive(is_interactive) \ + { \ + if (!YY_CURRENT_BUFFER) \ + { \ + yyensure_buffer_stack(); \ + YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin, YY_BUF_SIZE); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } +#define yy_set_bol(at_bol) \ + { \ + if (!YY_CURRENT_BUFFER) \ + { \ + yyensure_buffer_stack(); \ + YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin, YY_BUF_SIZE); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define yywrap() (/*CONSTCOND*/ 1) +#define YY_SKIP_YYWRAP +typedef flex_uint8_t YY_CHAR; + +FILE *yyin = NULL, *yyout = NULL; + +typedef int yy_state_type; + +extern int yylineno; +int yylineno = 1; + +extern char *yytext; +#ifdef yytext_ptr +#undef yytext_ptr +#endif +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state(void); +static yy_state_type yy_try_NUL_trans(yy_state_type current_state); +static int yy_get_next_buffer(void); +static void yynoreturn yy_fatal_error(const char *msg); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + yyleng = (yy_size_t)(yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; +#define YY_NUM_RULES 24 +#define YY_END_OF_BUFFER 25 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info +{ + flex_int32_t yy_verify; + flex_int32_t yy_nxt; +}; +static const flex_int16_t yy_accept[91] = { + 0, 0, 0, 25, 23, 17, 18, 23, 23, 6, 7, 3, 1, 8, 2, 23, 4, 16, 23, 19, 19, 23, 5, + 19, 19, 19, 19, 19, 18, 17, 0, 0, 0, 16, 16, 16, 19, 19, 0, 20, 19, 0, 0, 19, 19, 19, + 19, 19, 19, 19, 0, 21, 0, 0, 16, 0, 0, 16, 20, 20, 18, 0, 22, 0, 0, 9, 12, 19, 19, + 11, 19, 13, 18, 0, 16, 20, 0, 0, 0, 15, 19, 10, 0, 0, 19, 0, 19, 19, 19, 14, 0}; + +static const YY_CHAR yy_ec[256] = { + 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 4, 1, 1, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 1, 1, 1, 1, + 1, 1, 16, 16, 16, 16, 17, 18, 16, 16, 16, 16, 16, 16, 16, 16, 19, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 20, 21, 22, 23, 24, 1, 25, 26, 27, 28, + + 29, 26, 30, 26, 31, 26, 26, 32, 33, 34, 35, 26, 36, 37, 38, 39, 40, 26, 26, 26, 26, + 26, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + +static const YY_CHAR yy_meta[42] = {0, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 3, 4, 5, 6, 1, 6, 6, 6, 6, 1, + 5, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1}; + +static const flex_int16_t yy_base[98] = { + 0, 0, 0, 221, 254, 218, 254, 190, 29, 254, 254, 254, 254, 254, 254, 203, 254, + 32, 34, 204, 33, 42, 254, 39, 42, 47, 48, 50, 254, 213, 180, 50, 75, 199, + 52, 56, 200, 81, 84, 89, 89, 101, 103, 66, 53, 75, 92, 94, 97, 102, 183, + 254, 116, 128, 118, 134, 196, 112, 140, 144, 196, 105, 254, 145, 152, 195, 193, 138, + 144, 157, 132, 126, 254, 162, 117, 166, 174, 167, 181, 113, 173, 71, 178, 184, 160, + 187, 188, 190, 134, 64, 254, 224, 227, 229, 234, 238, 243, 247 + +}; + +static const flex_int16_t yy_def[98] = { + 0, 90, 1, 90, 90, 90, 90, 90, 91, 90, 90, 90, 90, 90, 90, 90, 90, 92, 93, 92, + 92, 90, 90, 92, 92, 92, 92, 92, 90, 90, 90, 91, 94, 90, 90, 92, 92, 92, 93, 95, + 92, 90, 90, 92, 92, 92, 92, 92, 92, 92, 90, 90, 96, 94, 90, 90, 90, 92, 97, 95, + 92, 90, 90, 90, 90, 92, 92, 92, 92, 92, 92, 92, 90, 96, 90, 97, 90, 90, 90, 92, + 92, 92, 90, 90, 92, 90, 92, 92, 92, 92, 0, 90, 90, 90, 90, 90, 90, 90 + +}; + +static const flex_int16_t yy_nxt[296] = { + 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 19, 19, 21, 4, 4, 22, + 19, 23, 19, 24, 19, 19, 19, 19, 19, 25, 19, 19, 19, 19, 26, 27, 19, 28, 31, 31, 34, 90, 35, 38, + 38, 37, 31, 90, 40, 31, 90, 38, 41, 42, 38, 90, 90, 37, 90, 31, 31, 90, 54, 43, 34, 55, 35, 31, + 46, 37, 31, 49, 90, 44, 90, 47, 51, 55, 45, 90, 48, 37, 52, 90, 52, 52, 56, 66, 56, 90, 65, 57, + 52, 38, 38, 52, 58, + + 90, 58, 58, 90, 38, 90, 60, 38, 90, 58, 61, 67, 58, 90, 41, 42, 63, 64, 76, 77, 51, 68, 62, 90, + 90, 57, 52, 69, 52, 52, 74, 54, 51, 70, 55, 71, 52, 90, 52, 52, 52, 52, 56, 90, 56, 90, 55, 74, + 52, 90, 58, 52, 58, 58, 58, 90, 58, 58, 63, 64, 58, 61, 89, 58, 58, 78, 51, 58, 90, 79, 81, 90, + 52, 62, 52, 52, 58, 80, 58, 58, 82, 83, 52, 61, 90, 52, 58, 76, 77, 58, 61, 82, 83, 61, 78, 62, + 61, 85, 86, 90, + + 85, 90, 62, 84, 90, 62, 90, 90, 62, 74, 72, 90, 33, 50, 29, 90, 33, 88, 30, 29, 90, 90, 90, 90, + 90, 90, 90, 87, 32, 32, 36, 90, 36, 39, 39, 53, 53, 90, 53, 53, 59, 90, 59, 59, 73, 73, 90, 73, + 73, 75, 90, 75, 75, 3, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90 + +}; + +static const flex_int16_t yy_chk[296] = { + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 8, 17, 20, 17, 18, + 18, 17, 8, 23, 20, 8, 24, 18, 21, 21, 18, 25, 26, 17, 27, 31, 31, 44, 34, 23, 35, 34, 35, 31, + 25, 35, 31, 27, 89, 24, 43, 26, 32, 34, 24, 81, 26, 35, 32, 45, 32, 32, 37, 44, 37, 37, 43, 37, + 32, 38, 38, 32, 39, + + 40, 39, 39, 46, 38, 47, 40, 38, 48, 39, 41, 45, 39, 49, 41, 41, 42, 42, 61, 61, 52, 46, 41, 57, + 79, 57, 52, 47, 52, 52, 74, 54, 53, 48, 54, 49, 52, 71, 53, 52, 53, 53, 55, 70, 55, 88, 54, 55, + 53, 67, 58, 53, 58, 58, 59, 68, 59, 59, 63, 63, 58, 64, 88, 58, 59, 64, 73, 59, 69, 67, 70, 84, + 73, 64, 73, 73, 75, 68, 75, 75, 77, 77, 73, 76, 80, 73, 75, 76, 76, 75, 78, 82, 82, 83, 78, 76, + 85, 83, 84, 86, + + 85, 87, 78, 80, 66, 83, 65, 60, 85, 56, 50, 36, 33, 30, 29, 19, 15, 87, 7, 5, 3, 0, 0, 0, + 0, 0, 0, 86, 91, 91, 92, 0, 92, 93, 93, 94, 94, 0, 94, 94, 95, 0, 95, 95, 96, 96, 0, 96, + 96, 97, 0, 97, 97, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90 + +}; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int yy_flex_debug; +int yy_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "lexer.l" +#line 2 "lexer.l" +#include "parser.h" +#define YY_USER_ACTION yylloc.first_line = yylloc.last_line = yylineno; +#line 544 "lexer.cpp" +#line 545 "lexer.cpp" + +#define INITIAL 0 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals(void); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy(void); + +int yyget_debug(void); + +void yyset_debug(int debug_flag); + +YY_EXTRA_TYPE yyget_extra(void); + +void yyset_extra(YY_EXTRA_TYPE user_defined); + +FILE *yyget_in(void); + +void yyset_in(FILE *_in_str); + +FILE *yyget_out(void); + +void yyset_out(FILE *_out_str); + +yy_size_t yyget_leng(void); + +char *yyget_text(void); + +int yyget_lineno(void); + +void yyset_lineno(int _line_number); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap(void); +#else +extern int yywrap(void); +#endif +#endif + +#ifndef YY_NO_UNPUT + +static void yyunput(int c, char *buf_ptr); + +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy(char *, const char *, int); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen(const char *); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput(void); +#else +static int input(void); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO \ + do \ + { \ + if (fwrite(yytext, (size_t)yyleng, 1, yyout)) \ + { \ + } \ + } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf, result, max_size) \ + if (YY_CURRENT_BUFFER_LVALUE->yy_is_interactive) \ + { \ + int c = '*'; \ + yy_size_t n; \ + for (n = 0; n < max_size && (c = getc(yyin)) != EOF && c != '\n'; ++n) \ + buf[n] = (char)c; \ + if (c == '\n') \ + buf[n++] = (char)c; \ + if (c == EOF && ferror(yyin)) \ + YY_FATAL_ERROR("input in flex scanner failed"); \ + result = n; \ + } \ + else \ + { \ + errno = 0; \ + while ((result = (int)fread(buf, 1, (yy_size_t)max_size, yyin)) == 0 && ferror(yyin)) \ + { \ + if (errno != EINTR) \ + { \ + YY_FATAL_ERROR("input in flex scanner failed"); \ + break; \ + } \ + errno = 0; \ + clearerr(yyin); \ + } \ + } + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error(msg) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex(void); + +#define YY_DECL int yylex(void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK /*LINTED*/ break; +#endif + +#define YY_RULE_SETUP YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + yy_state_type yy_current_state; + char *yy_cp, *yy_bp; + int yy_act; + + if (!(yy_init)) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if (!(yy_start)) + (yy_start) = 1; /* first start state */ + + if (!yyin) + yyin = stdin; + + if (!yyout) + yyout = stdout; + + if (!YY_CURRENT_BUFFER) + { + yyensure_buffer_stack(); + YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin, YY_BUF_SIZE); + } + + yy_load_buffer_state(); + } + + { +#line 12 "lexer.l" + +#line 765 "lexer.cpp" + + while (/*CONSTCOND*/ 1) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of yytext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); + yy_match: + do + { + YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if (yy_accept[yy_current_state]) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) + { + yy_current_state = (int)yy_def[yy_current_state]; + if (yy_current_state >= 91) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + ++yy_cp; + } while (yy_base[yy_current_state] != 254); + + yy_find_action: + yy_act = yy_accept[yy_current_state]; + if (yy_act == 0) + { /* have to back up */ + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + do_action: /* This label is used only to access EOF actions. */ + + switch (yy_act) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + + case 1: + YY_RULE_SETUP +#line 14 "lexer.l" + { + yylval.sval = strdup(yytext); + return OPERATOR; + } + YY_BREAK + case 2: + YY_RULE_SETUP +#line 15 "lexer.l" + { + yylval.sval = strdup(yytext); + return OPERATOR; + } + YY_BREAK + case 3: + YY_RULE_SETUP +#line 16 "lexer.l" + { + yylval.sval = strdup(yytext); + return OPERATOR; + } + YY_BREAK + case 4: + YY_RULE_SETUP +#line 17 "lexer.l" + { + yylval.sval = strdup(yytext); + return OPERATOR; + } + YY_BREAK + case 5: + YY_RULE_SETUP +#line 18 "lexer.l" + { + yylval.sval = strdup(yytext); + return OPERATOR; + } + YY_BREAK + case 6: + YY_RULE_SETUP +#line 19 "lexer.l" + { + return L_PAREN; + } + YY_BREAK + case 7: + YY_RULE_SETUP +#line 20 "lexer.l" + { + return R_PAREN; + } + YY_BREAK + case 8: + YY_RULE_SETUP +#line 21 "lexer.l" + { + return COMMA; + } + YY_BREAK + case 9: + YY_RULE_SETUP +#line 22 "lexer.l" + { + yylval.sval = strdup(yytext); + return FUNCTION; + } + YY_BREAK + case 10: + YY_RULE_SETUP +#line 23 "lexer.l" + { + yylval.sval = strdup(yytext); + return FUNCTION; + } + YY_BREAK + case 11: + YY_RULE_SETUP +#line 24 "lexer.l" + { + yylval.sval = strdup(yytext); + return FUNCTION; + } + YY_BREAK + case 12: + YY_RULE_SETUP +#line 25 "lexer.l" + { + yylval.sval = strdup(yytext); + return FUNCTION; + } + YY_BREAK + case 13: + YY_RULE_SETUP +#line 26 "lexer.l" + { + yylval.sval = strdup(yytext); + return FUNCTION; + } + YY_BREAK + case 14: + YY_RULE_SETUP +#line 27 "lexer.l" + { + yylval.sval = strdup(yytext); + return FUNCTION; + } + YY_BREAK + case 15: + YY_RULE_SETUP +#line 28 "lexer.l" + { + yylval.sval = strdup(yytext); + return FUNCTION; + } + YY_BREAK + case 16: + YY_RULE_SETUP +#line 31 "lexer.l" + { + yylval.dval = atof(yytext); + return NUMBER; + } + YY_BREAK + case 17: + YY_RULE_SETUP +#line 33 "lexer.l" + { /* ignore spaces */ + } + YY_BREAK + case 18: + /* rule 18 can match eol */ + YY_RULE_SETUP +#line 35 "lexer.l" + { + return ENDL; + } + YY_BREAK + case 19: + YY_RULE_SETUP +#line 37 "lexer.l" + { + yylval.sval = strdup(yytext); + return ALIAS; + } + YY_BREAK + case 20: + YY_RULE_SETUP +#line 39 "lexer.l" + { + yylval.sval = strndup(yytext + 1, strlen(yytext) - 1); + return PATH; + } + YY_BREAK + case 21: + YY_RULE_SETUP +#line 41 "lexer.l" + { + yylval.sval = strndup(yytext + 1, strlen(yytext) - 2); + return PATH; + } + YY_BREAK + case 22: + YY_RULE_SETUP +#line 43 "lexer.l" + { + yylval.sval = strndup(yytext + 1, strlen(yytext) - 2); + return INDICES; + } + YY_BREAK + case 23: + YY_RULE_SETUP +#line 45 "lexer.l" + { + printf("Error at line %d: unrecognized symbol \"%s\"\n", yylloc.first_line, + yytext); + exit(0); + } + YY_BREAK + case 24: + YY_RULE_SETUP +#line 47 "lexer.l" + ECHO; + YY_BREAK +#line 943 "lexer.cpp" + case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int)(yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if (YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ((yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans(yy_current_state); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if (yy_next_state) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else + switch (yy_get_next_buffer()) + { + case EOB_ACT_END_OF_FILE: { + (yy_did_buffer_switch_on_eof) = 0; + + if (yywrap()) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if (!(yy_did_buffer_switch_on_eof)) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR("fatal flex scanner internal error--no action found"); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of user's declarations */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer(void) +{ + char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + char *source = (yytext_ptr); + int number_to_move, i; + int ret_val; + + if ((yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1]) + YY_FATAL_ERROR("fatal flex scanner internal error--end of buffer missed"); + + if (YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ((yy_c_buf_p) - (yytext_ptr)-YY_MORE_ADJ == 1) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int)((yy_c_buf_p) - (yytext_ptr)-1); + + for (i = 0; i < number_to_move; ++i) + *(dest++) = *(source++); + + if (YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + yy_size_t num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while (num_to_read <= 0) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; + + int yy_c_buf_p_offset = (int)((yy_c_buf_p)-b->yy_ch_buf); + + if (b->yy_is_our_buffer) + { + yy_size_t new_size = b->yy_buf_size * 2; + + if (new_size <= 0) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc((void *)b->yy_ch_buf, (yy_size_t)(b->yy_buf_size + 2)); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = NULL; + + if (!b->yy_ch_buf) + YY_FATAL_ERROR("fatal error - scanner input buffer overflow"); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + } + + if (num_to_read > YY_READ_BUF_SIZE) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT((&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), (yy_n_chars), num_to_read); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ((yy_n_chars) == 0) + { + if (number_to_move == YY_MORE_ADJ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart(yyin); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) + { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = + (char *)yyrealloc((void *)YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t)new_size); + if (!YY_CURRENT_BUFFER_LVALUE->yy_ch_buf) + YY_FATAL_ERROR("out of dynamic memory in yy_get_next_buffer()"); + /* "- 2" to take care of EOB's */ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int)(new_size - 2); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state(void) +{ + yy_state_type yy_current_state; + char *yy_cp; + + yy_current_state = (yy_start); + + for (yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp) + { + YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 41); + if (yy_accept[yy_current_state]) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) + { + yy_current_state = (int)yy_def[yy_current_state]; + if (yy_current_state >= 91) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ +static yy_state_type yy_try_NUL_trans(yy_state_type yy_current_state) +{ + int yy_is_jam; + char *yy_cp = (yy_c_buf_p); + + YY_CHAR yy_c = 41; + if (yy_accept[yy_current_state]) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) + { + yy_current_state = (int)yy_def[yy_current_state]; + if (yy_current_state >= 91) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + yy_is_jam = (yy_current_state == 90); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_UNPUT + +static void yyunput(int c, char *yy_bp) +{ + char *yy_cp; + + yy_cp = (yy_c_buf_p); + + /* undo effects of setting up yytext */ + *yy_cp = (yy_hold_char); + + if (yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + yy_size_t number_to_move = (yy_n_chars) + 2; + char *dest = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while (source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf) + *--dest = *--source; + + yy_cp += (int)(dest - source); + yy_bp += (int)(dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = + (int)YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if (yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2) + YY_FATAL_ERROR("flex scanner push-back overflow"); + } + + *--yy_cp = (char)c; + + (yytext_ptr) = yy_bp; + (yy_hold_char) = *yy_cp; + (yy_c_buf_p) = yy_cp; +} + +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput(void) +#else +static int input(void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if (*(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ((yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + yy_size_t offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch (yy_get_next_buffer()) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart(yyin); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: { + if (yywrap()) + return 0; + + if (!(yy_did_buffer_switch_on_eof)) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *)(yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve yytext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ +void yyrestart(FILE *input_file) +{ + + if (!YY_CURRENT_BUFFER) + { + yyensure_buffer_stack(); + YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin, YY_BUF_SIZE); + } + + yy_init_buffer(YY_CURRENT_BUFFER, input_file); + yy_load_buffer_state(); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ +void yy_switch_to_buffer(YY_BUFFER_STATE new_buffer) +{ + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack(); + if (YY_CURRENT_BUFFER == new_buffer) + return; + + if (YY_CURRENT_BUFFER) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void yy_load_buffer_state(void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ +YY_BUFFER_STATE yy_create_buffer(FILE *file, int size) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE)yyalloc(sizeof(struct yy_buffer_state)); + if (!b) + YY_FATAL_ERROR("out of dynamic memory in yy_create_buffer()"); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *)yyalloc((yy_size_t)(b->yy_buf_size + 2)); + if (!b->yy_ch_buf) + YY_FATAL_ERROR("out of dynamic memory in yy_create_buffer()"); + + b->yy_is_our_buffer = 1; + + yy_init_buffer(b, file); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * + */ +void yy_delete_buffer(YY_BUFFER_STATE b) +{ + + if (!b) + return; + + if (b == YY_CURRENT_BUFFER) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE)0; + + if (b->yy_is_our_buffer) + yyfree((void *)b->yy_ch_buf); + + yyfree((void *)b); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ +static void yy_init_buffer(YY_BUFFER_STATE b, FILE *file) + +{ + int oerrno = errno; + + yy_flush_buffer(b); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER) + { + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty(fileno(file)) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ +void yy_flush_buffer(YY_BUFFER_STATE b) +{ + if (!b) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if (b == YY_CURRENT_BUFFER) + yy_load_buffer_state(); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void yypush_buffer_state(YY_BUFFER_STATE new_buffer) +{ + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(); + + /* This block is copied from yy_switch_to_buffer. */ + if (YY_CURRENT_BUFFER) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state(); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void yypop_buffer_state(void) +{ + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) + { + yy_load_buffer_state(); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack(void) +{ + yy_size_t num_to_alloc; + + if (!(yy_buffer_stack)) + { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ + (yy_buffer_stack) = + (struct yy_buffer_state **)yyalloc(num_to_alloc * sizeof(struct yy_buffer_state *)); + if (!(yy_buffer_stack)) + YY_FATAL_ERROR("out of dynamic memory in yyensure_buffer_stack()"); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state *)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1) + { + + /* Increase the buffer to prepare for a possible push. */ + yy_size_t grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state **)yyrealloc( + (yy_buffer_stack), num_to_alloc * sizeof(struct yy_buffer_state *)); + if (!(yy_buffer_stack)) + YY_FATAL_ERROR("out of dynamic memory in yyensure_buffer_stack()"); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, + grow_size * sizeof(struct yy_buffer_state *)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer(char *base, yy_size_t size) +{ + YY_BUFFER_STATE b; + + if (size < 2 || base[size - 2] != YY_END_OF_BUFFER_CHAR || + base[size - 1] != YY_END_OF_BUFFER_CHAR) + /* They forgot to leave room for the EOB's. */ + return NULL; + + b = (YY_BUFFER_STATE)yyalloc(sizeof(struct yy_buffer_state)); + if (!b) + YY_FATAL_ERROR("out of dynamic memory in yy_scan_buffer()"); + + b->yy_buf_size = (int)(size - 2); /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = NULL; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer(b); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string(const char *yystr) +{ + + return yy_scan_bytes(yystr, (int)strlen(yystr)); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes(const char *yybytes, yy_size_t _yybytes_len) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + yy_size_t i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = (yy_size_t)(_yybytes_len + 2); + buf = (char *)yyalloc(n); + if (!buf) + YY_FATAL_ERROR("out of dynamic memory in yy_scan_bytes()"); + + for (i = 0; i < _yybytes_len; ++i) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len + 1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer(buf, n); + if (!b) + YY_FATAL_ERROR("bad buffer in yy_scan_bytes()"); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yynoreturn yy_fatal_error(const char *msg) +{ + fprintf(stderr, "%s\n", msg); + exit(YY_EXIT_FAILURE); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yy_size_t yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg); \ + yytext[yyleng] = (yy_hold_char); \ + (yy_c_buf_p) = yytext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + yyleng = yyless_macro_arg; \ + } while (0) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int yyget_lineno(void) { return yylineno; } + +/** Get the input stream. + * + */ +FILE *yyget_in(void) { return yyin; } + +/** Get the output stream. + * + */ +FILE *yyget_out(void) { return yyout; } + +/** Get the length of the current token. + * + */ +yy_size_t yyget_leng(void) { return yyleng; } + +/** Get the current token. + * + */ + +char *yyget_text(void) { return yytext; } + +/** Set the current line number. + * @param _line_number line number + * + */ +void yyset_lineno(int _line_number) { yylineno = _line_number; } + +/** Set the input stream. This does not discard the current + * input buffer. + * @param _in_str A readable stream. + * + * @see yy_switch_to_buffer + */ +void yyset_in(FILE *_in_str) { yyin = _in_str; } + +void yyset_out(FILE *_out_str) { yyout = _out_str; } + +int yyget_debug(void) { return yy_flex_debug; } + +void yyset_debug(int _bdebug) { yy_flex_debug = _bdebug; } + +static int yy_init_globals(void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = NULL; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = NULL; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = NULL; + yyout = NULL; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy(void) +{ + + /* Pop the buffer stack, destroying each element. */ + while (YY_CURRENT_BUFFER) + { + yy_delete_buffer(YY_CURRENT_BUFFER); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(); + } + + /* Destroy the stack itself. */ + yyfree((yy_buffer_stack)); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals(); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy(char *s1, const char *s2, int n) +{ + + int i; + for (i = 0; i < n; ++i) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen(const char *s) +{ + int n; + for (n = 0; s[n]; ++n) + ; + + return n; +} +#endif + +void *yyalloc(yy_size_t size) { return malloc(size); } + +void *yyrealloc(void *ptr, yy_size_t size) +{ + + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return realloc(ptr, size); +} + +void yyfree(void *ptr) { free((char *)ptr); /* see yyrealloc() for (char *) cast */ } + +#define YYTABLES_NAME "yytables" + +#line 47 "lexer.l" diff --git a/source/adios2/toolkit/derived/parser/lexer.h b/source/adios2/toolkit/derived/parser/lexer.h new file mode 100644 index 0000000000..75c3a14657 --- /dev/null +++ b/source/adios2/toolkit/derived/parser/lexer.h @@ -0,0 +1,476 @@ +#ifndef yyHEADER_H +#define yyHEADER_H 1 +#define yyIN_HEADER 1 + +#line 5 "lexer.h" + +#line 7 "lexer.h" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 6 +#define YY_FLEX_SUBMINOR_VERSION 4 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +typedef uint64_t flex_uint64_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767 - 1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647 - 1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#ifndef SIZE_MAX +#define SIZE_MAX (~(size_t)0) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +/* begin standard C++ headers. */ + +/* TODO: this is always defined, so inline it */ +#define yyconst const + +#if defined(__GNUC__) && __GNUC__ >= 3 +#define yynoreturn __attribute__((__noreturn__)) +#else +#define yynoreturn +#endif + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +extern yy_size_t yyleng; + +extern FILE *yyin, *yyout; + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state +{ + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + int yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + yy_size_t yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +}; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +void yyrestart(FILE *input_file); +void yy_switch_to_buffer(YY_BUFFER_STATE new_buffer); +YY_BUFFER_STATE yy_create_buffer(FILE *file, int size); +void yy_delete_buffer(YY_BUFFER_STATE b); +void yy_flush_buffer(YY_BUFFER_STATE b); +void yypush_buffer_state(YY_BUFFER_STATE new_buffer); +void yypop_buffer_state(void); + +YY_BUFFER_STATE yy_scan_buffer(char *base, yy_size_t size); +YY_BUFFER_STATE yy_scan_string(const char *yy_str); +YY_BUFFER_STATE yy_scan_bytes(const char *bytes, yy_size_t len); + +void *yyalloc(yy_size_t); +void *yyrealloc(void *, yy_size_t); +void yyfree(void *); + +/* Begin user sect3 */ + +#define yywrap() (/*CONSTCOND*/ 1) +#define YY_SKIP_YYWRAP + +extern int yylineno; + +extern char *yytext; +#ifdef yytext_ptr +#undef yytext_ptr +#endif +#define yytext_ptr yytext + +#ifdef YY_HEADER_EXPORT_START_CONDITIONS +#define INITIAL 0 + +#endif + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy(void); + +int yyget_debug(void); + +void yyset_debug(int debug_flag); + +YY_EXTRA_TYPE yyget_extra(void); + +void yyset_extra(YY_EXTRA_TYPE user_defined); + +FILE *yyget_in(void); + +void yyset_in(FILE *_in_str); + +FILE *yyget_out(void); + +void yyset_out(FILE *_out_str); + +yy_size_t yyget_leng(void); + +char *yyget_text(void); + +int yyget_lineno(void); + +void yyset_lineno(int _line_number); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap(void); +#else +extern int yywrap(void); +#endif +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy(char *, const char *, int); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen(const char *); +#endif + +#ifndef YY_NO_INPUT + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex(void); + +#define YY_DECL int yylex(void) +#endif /* !YY_DECL */ + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +#undef YY_NEW_FILE +#undef YY_FLUSH_BUFFER +#undef yy_set_bol +#undef yy_new_buffer +#undef yy_set_interactive +#undef YY_DO_BEFORE_ACTION + +#ifdef YY_DECL_IS_OURS +#undef YY_DECL_IS_OURS +#undef YY_DECL +#endif + +#ifndef yy_create_buffer_ALREADY_DEFINED +#undef yy_create_buffer +#endif +#ifndef yy_delete_buffer_ALREADY_DEFINED +#undef yy_delete_buffer +#endif +#ifndef yy_scan_buffer_ALREADY_DEFINED +#undef yy_scan_buffer +#endif +#ifndef yy_scan_string_ALREADY_DEFINED +#undef yy_scan_string +#endif +#ifndef yy_scan_bytes_ALREADY_DEFINED +#undef yy_scan_bytes +#endif +#ifndef yy_init_buffer_ALREADY_DEFINED +#undef yy_init_buffer +#endif +#ifndef yy_flush_buffer_ALREADY_DEFINED +#undef yy_flush_buffer +#endif +#ifndef yy_load_buffer_state_ALREADY_DEFINED +#undef yy_load_buffer_state +#endif +#ifndef yy_switch_to_buffer_ALREADY_DEFINED +#undef yy_switch_to_buffer +#endif +#ifndef yypush_buffer_state_ALREADY_DEFINED +#undef yypush_buffer_state +#endif +#ifndef yypop_buffer_state_ALREADY_DEFINED +#undef yypop_buffer_state +#endif +#ifndef yyensure_buffer_stack_ALREADY_DEFINED +#undef yyensure_buffer_stack +#endif +#ifndef yylex_ALREADY_DEFINED +#undef yylex +#endif +#ifndef yyrestart_ALREADY_DEFINED +#undef yyrestart +#endif +#ifndef yylex_init_ALREADY_DEFINED +#undef yylex_init +#endif +#ifndef yylex_init_extra_ALREADY_DEFINED +#undef yylex_init_extra +#endif +#ifndef yylex_destroy_ALREADY_DEFINED +#undef yylex_destroy +#endif +#ifndef yyget_debug_ALREADY_DEFINED +#undef yyget_debug +#endif +#ifndef yyset_debug_ALREADY_DEFINED +#undef yyset_debug +#endif +#ifndef yyget_extra_ALREADY_DEFINED +#undef yyget_extra +#endif +#ifndef yyset_extra_ALREADY_DEFINED +#undef yyset_extra +#endif +#ifndef yyget_in_ALREADY_DEFINED +#undef yyget_in +#endif +#ifndef yyset_in_ALREADY_DEFINED +#undef yyset_in +#endif +#ifndef yyget_out_ALREADY_DEFINED +#undef yyget_out +#endif +#ifndef yyset_out_ALREADY_DEFINED +#undef yyset_out +#endif +#ifndef yyget_leng_ALREADY_DEFINED +#undef yyget_leng +#endif +#ifndef yyget_text_ALREADY_DEFINED +#undef yyget_text +#endif +#ifndef yyget_lineno_ALREADY_DEFINED +#undef yyget_lineno +#endif +#ifndef yyset_lineno_ALREADY_DEFINED +#undef yyset_lineno +#endif +#ifndef yyget_column_ALREADY_DEFINED +#undef yyget_column +#endif +#ifndef yyset_column_ALREADY_DEFINED +#undef yyset_column +#endif +#ifndef yywrap_ALREADY_DEFINED +#undef yywrap +#endif +#ifndef yyget_lval_ALREADY_DEFINED +#undef yyget_lval +#endif +#ifndef yyset_lval_ALREADY_DEFINED +#undef yyset_lval +#endif +#ifndef yyget_lloc_ALREADY_DEFINED +#undef yyget_lloc +#endif +#ifndef yyset_lloc_ALREADY_DEFINED +#undef yyset_lloc +#endif +#ifndef yyalloc_ALREADY_DEFINED +#undef yyalloc +#endif +#ifndef yyrealloc_ALREADY_DEFINED +#undef yyrealloc +#endif +#ifndef yyfree_ALREADY_DEFINED +#undef yyfree +#endif +#ifndef yytext_ALREADY_DEFINED +#undef yytext +#endif +#ifndef yyleng_ALREADY_DEFINED +#undef yyleng +#endif +#ifndef yyin_ALREADY_DEFINED +#undef yyin +#endif +#ifndef yyout_ALREADY_DEFINED +#undef yyout +#endif +#ifndef yy_flex_debug_ALREADY_DEFINED +#undef yy_flex_debug +#endif +#ifndef yylineno_ALREADY_DEFINED +#undef yylineno +#endif +#ifndef yytables_fload_ALREADY_DEFINED +#undef yytables_fload +#endif +#ifndef yytables_destroy_ALREADY_DEFINED +#undef yytables_destroy +#endif +#ifndef yyTABLES_NAME_ALREADY_DEFINED +#undef yyTABLES_NAME +#endif + +#line 47 "lexer.l" + +#line 476 "lexer.h" +#undef yyIN_HEADER +#endif /* yyHEADER_H */ diff --git a/source/adios2/toolkit/derived/parser/lexer.l b/source/adios2/toolkit/derived/parser/lexer.l new file mode 100644 index 0000000000..f81a98bcf9 --- /dev/null +++ b/source/adios2/toolkit/derived/parser/lexer.l @@ -0,0 +1,47 @@ +%{ +#include "parser.hpp" +#define YY_USER_ACTION yylloc.first_line = yylloc.last_line = yylineno; +%} + +%option noyywrap + + +DIGIT [0-9] +CHAR ([a-z]|[A-Z]) + +%% + +"+" {yylval.sval=strdup(yytext); return OPERATOR;} +"-" {yylval.sval=strdup(yytext); return OPERATOR;} +"*" {yylval.sval=strdup(yytext); return OPERATOR;} +"/" {yylval.sval=strdup(yytext); return OPERATOR;} +"^" {yylval.sval=strdup(yytext); return OPERATOR;} +"(" {return L_PAREN;} +")" {return R_PAREN;} +"," {return COMMA;} +"add" {yylval.sval=strdup(yytext); return FUNCTION;} +"sqrt" {yylval.sval=strdup(yytext); return FUNCTION;} +"sin" {yylval.sval=strdup(yytext); return FUNCTION;} +"cos" {yylval.sval=strdup(yytext); return FUNCTION;} +"tan" {yylval.sval=strdup(yytext); return FUNCTION;} +"magnitude" {yylval.sval=strdup(yytext); return FUNCTION;} +"curl" {yylval.sval=strdup(yytext); return FUNCTION;} + + +(\.{DIGIT}+)|({DIGIT}+(\.{DIGIT}*)?([eE][+-]?[0-9]+)?) {yylval.dval = atof(yytext); return NUMBER;} + +[ \t]+ {/* ignore spaces */} + +(\n|\0|EOF|$end) {return ENDL;} + +({CHAR}|{DIGIT}|_)+ {yylval.sval=strdup(yytext); return ALIAS;} + +:(\\|\/|_|{DIGIT})*{CHAR}+(\\|\/|-|_|{DIGIT}|{CHAR})* {yylval.sval=strndup(yytext + 1,strlen(yytext)-1); return PATH;} + +'(\\|\/|_|{DIGIT})*{CHAR}+(\\|\/|-|_|{DIGIT}|{CHAR})*' {yylval.sval=strndup(yytext + 1,strlen(yytext)-2); return PATH;} + +"["({DIGIT}+|{DIGIT}*":"{DIGIT}*":"{DIGIT}*)(,({DIGIT}+|{DIGIT}*":"{DIGIT}*":"{DIGIT}*))*"]" {yylval.sval=strndup(yytext + 1,strlen(yytext)-2); return INDICES;} + +. {printf("Error at line %d: unrecognized symbol \"%s\"\n", yylloc.first_line, yytext); exit(0);} + +%% \ No newline at end of file diff --git a/source/adios2/toolkit/derived/parser/parser.cpp b/source/adios2/toolkit/derived/parser/parser.cpp new file mode 100644 index 0000000000..03938fc8d6 --- /dev/null +++ b/source/adios2/toolkit/derived/parser/parser.cpp @@ -0,0 +1,1666 @@ +/* A Bison parser, made by GNU Bison 2.3. */ + +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.3" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Using locations. */ +#define YYLSP_NEEDED 1 + +/* Tokens. */ +#ifndef YYTOKENTYPE +#define YYTOKENTYPE +/* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ +enum yytokentype +{ + COMMA = 258, + L_PAREN = 259, + R_PAREN = 260, + ENDL = 261, + FUNCTION = 262, + OPERATOR = 263, + INDICES = 264, + NUMBER = 265, + ALIAS = 266, + PATH = 267 +}; +#endif +/* Tokens. */ +#define COMMA 258 +#define L_PAREN 259 +#define R_PAREN 260 +#define ENDL 261 +#define FUNCTION 262 +#define OPERATOR 263 +#define INDICES 264 +#define NUMBER 265 +#define ALIAS 266 +#define PATH 267 + +/* Copy the first part of user declarations. */ +#line 2 "parser.y" + +#include "parser.h" +#include "lexer.h" +#include +#include +#include +#include +#include +#include + +extern int yyparse(std::stack *expr_stack); + +static void *yyparse_value; + +void yyerror(std::stack *expr_stack, const char *msg); + +namespace adios2 +{ +namespace detail +{ +void *createExpr(std::stack *, std::string, const char *, double, size_t); +} +} + +/* Enabling traces. */ +#ifndef YYDEBUG +#define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +#undef YYERROR_VERBOSE +#define YYERROR_VERBOSE 1 +#else +#define YYERROR_VERBOSE 1 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +#define YYTOKEN_TABLE 0 +#endif + +#if !defined YYSTYPE && !defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +#line 25 "parser.y" +{ + double dval; + int ival; + char *sval; + void *expr_ptr; +} +/* Line 193 of yacc.c. */ +#line 148 "parser.cpp" +YYSTYPE; +#define yystype YYSTYPE /* obsolescent; will be withdrawn */ +#define YYSTYPE_IS_DECLARED 1 +#define YYSTYPE_IS_TRIVIAL 1 +#endif + +#if !defined YYLTYPE && !defined YYLTYPE_IS_DECLARED +typedef struct YYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} YYLTYPE; +#define yyltype YYLTYPE /* obsolescent; will be withdrawn */ +#define YYLTYPE_IS_DECLARED 1 +#define YYLTYPE_IS_TRIVIAL 1 +#endif + +/* Copy the second part of user declarations. */ + +/* Line 216 of yacc.c. */ +#line 173 "parser.cpp" + +#ifdef short +#undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +#ifdef __SIZE_TYPE__ +#define YYSIZE_T __SIZE_TYPE__ +#elif defined size_t +#define YYSIZE_T size_t +#elif !defined YYSIZE_T && \ + (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER) +#include /* INFRINGES ON USER NAME SPACE */ +#define YYSIZE_T size_t +#else +#define YYSIZE_T unsigned int +#endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T)-1) + +#ifndef YY_ +#if defined YYENABLE_NLS && YYENABLE_NLS +#if ENABLE_NLS +#include /* INFRINGES ON USER NAME SPACE */ +#define YY_(msgid) dgettext("bison-runtime", msgid) +#endif +#endif +#ifndef YY_ +#define YY_(msgid) msgid +#endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if !defined lint || defined __GNUC__ +#define YYUSE(e) ((void)(e)) +#else +#define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +#define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER) +static int YYID(int i) +#else +static int YYID(i) +int i; +#endif +{ + return i; +} +#endif + +#if !defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +#ifdef YYSTACK_USE_ALLOCA +#if YYSTACK_USE_ALLOCA +#ifdef __GNUC__ +#define YYSTACK_ALLOC __builtin_alloca +#elif defined __BUILTIN_VA_ARG_INCR +#include /* INFRINGES ON USER NAME SPACE */ +#elif defined _AIX +#define YYSTACK_ALLOC __alloca +#elif defined _MSC_VER +#include /* INFRINGES ON USER NAME SPACE */ +#define alloca _alloca +#else +#define YYSTACK_ALLOC alloca +#if !defined _ALLOCA_H && !defined _STDLIB_H && \ + (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER) +#include /* INFRINGES ON USER NAME SPACE */ +#ifndef _STDLIB_H +#define _STDLIB_H 1 +#endif +#endif +#endif +#endif +#endif + +#ifdef YYSTACK_ALLOC +/* Pacify GCC's `empty if-body' warning. */ +#define YYSTACK_FREE(Ptr) \ + do \ + { /* empty */ \ + ; \ + } while (YYID(0)) +#ifndef YYSTACK_ALLOC_MAXIMUM +/* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +#define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +#endif +#else +#define YYSTACK_ALLOC YYMALLOC +#define YYSTACK_FREE YYFREE +#ifndef YYSTACK_ALLOC_MAXIMUM +#define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +#endif +#if (defined __cplusplus && !defined _STDLIB_H && \ + !((defined YYMALLOC || defined malloc) && (defined YYFREE || defined free))) +#include /* INFRINGES ON USER NAME SPACE */ +#ifndef _STDLIB_H +#define _STDLIB_H 1 +#endif +#endif +#ifndef YYMALLOC +#define YYMALLOC malloc +#if !defined malloc && !defined _STDLIB_H && \ + (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER) +void *malloc(YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +#endif +#endif +#ifndef YYFREE +#define YYFREE free +#if !defined free && !defined _STDLIB_H && \ + (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER) +void free(void *); /* INFRINGES ON USER NAME SPACE */ +#endif +#endif +#endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + +#if (!defined yyoverflow && \ + (!defined __cplusplus || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL && \ + defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss; + YYSTYPE yyvs; + YYLTYPE yyls; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +#define YYSTACK_GAP_MAXIMUM (sizeof(union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +#define YYSTACK_BYTES(N) \ + ((N) * (sizeof(yytype_int16) + sizeof(YYSTYPE) + sizeof(YYLTYPE)) + 2 * YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +#ifndef YYCOPY +#if defined __GNUC__ && 1 < __GNUC__ +#define YYCOPY(To, From, Count) __builtin_memcpy(To, From, (Count) * sizeof(*(From))) +#else +#define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } while (YYID(0)) +#endif +#endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +#define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY(&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof(*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof(*yyptr); \ + } while (YYID(0)) + +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 16 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 37 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 13 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 5 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 16 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 28 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 267 + +#define YYTRANSLATE(YYX) ((unsigned int)(YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = { + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint8 yyprhs[] = {0, 0, 3, 4, 7, 10, 13, 16, 20, + 24, 26, 28, 31, 33, 35, 39, 43}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = {14, 0, -1, -1, 6, 14, -1, 15, 14, -1, 17, 14, -1, 11, 12, -1, + 11, 12, 9, -1, 16, 3, 17, -1, 17, -1, 11, -1, 11, 9, -1, 12, + -1, 10, -1, 4, 17, 5, -1, 17, 8, 17, -1, 7, 4, 16, 5, -1}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint8 yyrline[] = {0, 51, 51, 52, 53, 54, 57, 58, 65, + 66, 69, 70, 71, 72, 73, 74, 75}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = {"$end", "error", "$undefined", "COMMA", "L_PAREN", + "R_PAREN", "ENDL", "FUNCTION", "OPERATOR", "INDICES", + "NUMBER", "ALIAS", "PATH", "$accept", "input", + "decl", "list", "exp", 0}; +#endif + +#ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = {0, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267}; +#endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = {0, 13, 14, 14, 14, 14, 15, 15, 16, + 16, 17, 17, 17, 17, 17, 17, 17}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = {0, 2, 0, 2, 2, 2, 2, 3, 3, 1, 1, 2, 1, 1, 3, 3, 4}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = {2, 0, 2, 0, 13, 10, 12, 0, 2, 2, 10, 0, 3, 0, + 11, 6, 1, 4, 0, 5, 14, 0, 9, 7, 15, 0, 16, 8}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = {-1, 7, 8, 21, 9}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -4 +static const yytype_int8 yypact[] = {9, 18, 9, -2, -4, 2, -4, 6, 9, -3, 1, 26, -4, 18, + -4, 14, -4, -4, 18, -4, -4, 32, 10, -4, 10, 18, -4, 10}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = {-4, 24, -4, -4, -1}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -1 +static const yytype_uint8 yytable[] = {11, 1, 13, 2, 3, 18, 16, 4, 5, 6, 14, 14, 22, + 1, 15, 2, 3, 24, 18, 4, 5, 6, 1, 23, 27, 3, + 12, 0, 4, 10, 6, 20, 17, 19, 18, 25, 0, 26}; + +static const yytype_int8 yycheck[] = {1, 4, 4, 6, 7, 8, 0, 10, 11, 12, 9, 9, 13, + 4, 12, 6, 7, 18, 8, 10, 11, 12, 4, 9, 25, 7, + 2, -1, 10, 11, 12, 5, 8, 9, 8, 3, -1, 5}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = {0, 4, 6, 7, 10, 11, 12, 14, 15, 17, 11, 17, 14, 4, + 9, 12, 0, 14, 8, 14, 5, 16, 17, 9, 17, 3, 5, 17}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ + do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE(yychar); \ + YYPOPSTACK(1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror(expr_stack, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ + while (YYID(0)) + +#define YYTERROR 1 +#define YYERRCODE 256 + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +#define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID(N)) \ + { \ + (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC(Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC(Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC(Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = YYRHSLOC(Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = YYRHSLOC(Rhs, 0).last_column; \ + } \ + while (YYID(0)) +#endif + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +#if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL +#define YY_LOCATION_PRINT(File, Loc) \ + fprintf(File, "%d.%d-%d.%d", (Loc).first_line, (Loc).first_column, (Loc).last_line, \ + (Loc).last_column) +#else +#define YY_LOCATION_PRINT(File, Loc) ((void)0) +#endif +#endif + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +#define YYLEX yylex(YYLEX_PARAM) +#else +#define YYLEX yylex() +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +#ifndef YYFPRINTF +#include /* INFRINGES ON USER NAME SPACE */ +#define YYFPRINTF fprintf +#endif + +#define YYDPRINTF(Args) \ + do \ + { \ + if (yydebug) \ + YYFPRINTF Args; \ + } while (YYID(0)) + +#define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ + do \ + { \ + if (yydebug) \ + { \ + YYFPRINTF(stderr, "%s ", Title); \ + yy_symbol_print(stderr, Type, Value, Location, expr_stack); \ + YYFPRINTF(stderr, "\n"); \ + } \ + } while (YYID(0)) + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER) +static void yy_symbol_value_print(FILE *yyoutput, int yytype, YYSTYPE const *const yyvaluep, + YYLTYPE const *const yylocationp, + std::stack *expr_stack) +#else +static void yy_symbol_value_print(yyoutput, yytype, yyvaluep, yylocationp, + expr_stack) FILE *yyoutput; +int yytype; +YYSTYPE const *const yyvaluep; +YYLTYPE const *const yylocationp; +std::stack *expr_stack; +#endif +{ + if (!yyvaluep) + return; + YYUSE(yylocationp); + YYUSE(expr_stack); +#ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT(yyoutput, yytoknum[yytype], *yyvaluep); +#else + YYUSE(yyoutput); +#endif + switch (yytype) + { + default: + break; + } +} + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER) +static void yy_symbol_print(FILE *yyoutput, int yytype, YYSTYPE const *const yyvaluep, + YYLTYPE const *const yylocationp, + std::stack *expr_stack) +#else +static void yy_symbol_print(yyoutput, yytype, yyvaluep, yylocationp, expr_stack) FILE *yyoutput; +int yytype; +YYSTYPE const *const yyvaluep; +YYLTYPE const *const yylocationp; +std::stack *expr_stack; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF(yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF(yyoutput, "nterm %s (", yytname[yytype]); + + YY_LOCATION_PRINT(yyoutput, *yylocationp); + YYFPRINTF(yyoutput, ": "); + yy_symbol_value_print(yyoutput, yytype, yyvaluep, yylocationp, expr_stack); + YYFPRINTF(yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER) +static void yy_stack_print(yytype_int16 *bottom, yytype_int16 *top) +#else +static void yy_stack_print(bottom, top) yytype_int16 *bottom; +yytype_int16 *top; +#endif +{ + YYFPRINTF(stderr, "Stack now"); + for (; bottom <= top; ++bottom) + YYFPRINTF(stderr, " %d", *bottom); + YYFPRINTF(stderr, "\n"); +} + +#define YY_STACK_PRINT(Bottom, Top) \ + do \ + { \ + if (yydebug) \ + yy_stack_print((Bottom), (Top)); \ + } while (YYID(0)) + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER) +static void yy_reduce_print(YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, + std::stack *expr_stack) +#else +static void yy_reduce_print(yyvsp, yylsp, yyrule, expr_stack) YYSTYPE *yyvsp; +YYLTYPE *yylsp; +int yyrule; +std::stack *expr_stack; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF(stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + fprintf(stderr, " $%d = ", yyi + 1); + yy_symbol_print(stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]), + &(yylsp[(yyi + 1) - (yynrhs)]), expr_stack); + fprintf(stderr, "\n"); + } +} + +#define YY_REDUCE_PRINT(Rule) \ + do \ + { \ + if (yydebug) \ + yy_reduce_print(yyvsp, yylsp, Rule, expr_stack); \ + } while (YYID(0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +#define YYDPRINTF(Args) +#define YY_SYMBOL_PRINT(Title, Type, Value, Location) +#define YY_STACK_PRINT(Bottom, Top) +#define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +#if YYERROR_VERBOSE + +#ifndef yystrlen +#if defined __GLIBC__ && defined _STRING_H +#define yystrlen strlen +#else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T yystrlen(const char *yystr) +#else +static YYSIZE_T yystrlen(yystr) const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +#endif +#endif + +#ifndef yystpcpy +#if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +#define yystpcpy stpcpy +#else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER) +static char *yystpcpy(char *yydest, const char *yysrc) +#else +static char *yystpcpy(yydest, yysrc) +char *yydest; +const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +#endif +#endif + +#ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T yytnamerr(char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes:; + } + + if (!yyres) + return yystrlen(yystr); + + return yystpcpy(yyres, yystr) - yyres; +} +#endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T yysyntax_error(char *yyresult, int yystate, int yychar) +{ + int yyn = yypact[yystate]; + + if (!(YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE(yychar); + YYSIZE_T yysize0 = yytnamerr(0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum + { + YYERROR_VERBOSE_ARGS_MAXIMUM = 5 + }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +#if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +#endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy(yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr(0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy(yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen(yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr(yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } +} +#endif /* YYERROR_VERBOSE */ + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER) +static void yydestruct(const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, + std::stack *expr_stack) +#else +static void yydestruct(yymsg, yytype, yyvaluep, yylocationp, expr_stack) const char *yymsg; +int yytype; +YYSTYPE *yyvaluep; +YYLTYPE *yylocationp; +std::stack *expr_stack; +#endif +{ + YYUSE(yyvaluep); + YYUSE(yylocationp); + YYUSE(expr_stack); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT(yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + + default: + break; + } +} + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse(void *YYPARSE_PARAM); +#else +int yyparse(); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse(std::stack *expr_stack); +#else +int yyparse(); +#endif +#endif /* ! YYPARSE_PARAM */ + +/* The look-ahead symbol. */ +int yychar; + +/* The semantic value of the look-ahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; +/* Location data for the look-ahead symbol. */ +YYLTYPE yylloc; + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER) +int yyparse(void *YYPARSE_PARAM) +#else +int yyparse(YYPARSE_PARAM) void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER) +int yyparse(std::stack *expr_stack) +#else +int yyparse(expr_stack) std::stack *expr_stack; +#endif +#endif +{ + + int yystate; + int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Look-ahead token as an internal (translated) token number. */ + int yytoken = 0; +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss = yyssa; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp; + + /* The location stack. */ + YYLTYPE yylsa[YYINITDEPTH]; + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + /* The locations where the error started and ended. */ + YYLTYPE yyerror_range[2]; + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + YYLTYPE yyloc; + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + YYDPRINTF((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + yylsp = yyls; +#if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL + /* Initialize the default location before parsing starts. */ + yylloc.first_line = yylloc.last_line = 1; + yylloc.first_column = yylloc.last_column = 0; +#endif + + goto yysetstate; + + /*------------------------------------------------------------. + | yynewstate -- Push a new state, which is found in yystate. | + `------------------------------------------------------------*/ +yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + +yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + YYLTYPE *yyls1 = yyls; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow(YY_("memory exhausted"), &yyss1, yysize * sizeof(*yyssp), &yyvs1, + yysize * sizeof(*yyvsp), &yyls1, yysize * sizeof(*yylsp), &yystacksize); + yyls = yyls1; + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +#ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +#else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = (union yyalloc *)YYSTACK_ALLOC(YYSTACK_BYTES(yystacksize)); + if (!yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE(yyss); + YYSTACK_RELOCATE(yyvs); + YYSTACK_RELOCATE(yyls); +#undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE(yyss1); + } +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + yylsp = yyls + yysize - 1; + + YYDPRINTF((stderr, "Stack size increased to %lu\n", (unsigned long int)yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + look-ahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to look-ahead token. */ + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a look-ahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE(yychar); + YY_SYMBOL_PRINT("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the look-ahead token. */ + YY_SYMBOL_PRINT("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + *++yylsp = yylloc; + goto yynewstate; + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1 - yylen]; + + /* Default location. */ + YYLLOC_DEFAULT(yyloc, (yylsp - yylen), yylen); + YY_REDUCE_PRINT(yyn); + switch (yyn) + { + case 2: +#line 51 "parser.y" + { + ; + } + break; + + case 3: +#line 52 "parser.y" + { + ; + } + break; + + case 4: +#line 53 "parser.y" + { + ; + } + break; + + case 5: +#line 54 "parser.y" + { /*yyparse_value = $1->expression;*/ + ; + } + break; + + case 6: +#line 57 "parser.y" + { + adios2::detail::ASTNode::add_lookup_entry((yyvsp[(1) - (2)].sval), (yyvsp[(2) - (2)].sval), + ""); + ; + } + break; + + case 7: +#line 58 "parser.y" + { + adios2::detail::ASTNode::add_lookup_entry((yyvsp[(1) - (3)].sval), (yyvsp[(2) - (3)].sval), + (yyvsp[(3) - (3)].sval)); + ; + } + break; + + case 8: +#line 65 "parser.y" + { + (yyval.ival) = (yyvsp[(1) - (3)].ival) + 1; + ; + } + break; + + case 9: +#line 66 "parser.y" + { + (yyval.ival) = 1; + ; + } + break; + + case 10: +#line 69 "parser.y" + { + (yyval.expr_ptr) = createExpr(expr_stack, "ALIAS", (yyvsp[(1) - (1)].sval), 0, 0); + ; + } + break; + + case 11: +#line 70 "parser.y" + { + createExpr(expr_stack, "ALIAS", (yyvsp[(1) - (2)].sval), 0, 0); + (yyval.expr_ptr) = createExpr(expr_stack, "INDEX", (yyvsp[(2) - (2)].sval), 0, 1); + ; + } + break; + + case 12: +#line 71 "parser.y" + { + (yyval.expr_ptr) = createExpr(expr_stack, "PATH", (yyvsp[(1) - (1)].sval), 0, 0); + ; + } + break; + + case 13: +#line 72 "parser.y" + { + (yyval.expr_ptr) = createExpr(expr_stack, "NUM", "", (yyvsp[(1) - (1)].dval), 0); + ; + } + break; + + case 14: +#line 73 "parser.y" + { + (yyval.expr_ptr) = (yyvsp[(2) - (3)].expr_ptr); + ; + } + break; + + case 15: +#line 74 "parser.y" + { + (yyval.expr_ptr) = createExpr(expr_stack, (yyvsp[(2) - (3)].sval), "", 0, 2); + ; + } + break; + + case 16: +#line 75 "parser.y" + { + (yyval.expr_ptr) = + createExpr(expr_stack, (yyvsp[(1) - (4)].sval), "", 0, (yyvsp[(3) - (4)].ival)); + ; + } + break; + +/* Line 1267 of yacc.c. */ +#line 1480 "parser.cpp" + default: + break; + } + YY_SYMBOL_PRINT("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK(yylen); + yylen = 0; + YY_STACK_PRINT(yyss, yyssp); + + *++yyvsp = yyval; + *++yylsp = yyloc; + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if !YYERROR_VERBOSE + yyerror(expr_stack, YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error(0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (!(yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE(yymsg); + yymsg = (char *)YYSTACK_ALLOC(yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void)yysyntax_error(yymsg, yystate, yychar); + yyerror(expr_stack, yymsg); + } + else + { + yyerror(expr_stack, YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } + } +#endif + } + + yyerror_range[0] = yylloc; + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse look-ahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct("Error: discarding", yytoken, &yylval, &yylloc, expr_stack); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse look-ahead token after shifting the error + token. */ + goto yyerrlab1; + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + yyerror_range[0] = yylsp[1 - yylen]; + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK(yylen); + yylen = 0; + YY_STACK_PRINT(yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + yyerror_range[0] = *yylsp; + yydestruct("Error: popping", yystos[yystate], yyvsp, yylsp, expr_stack); + YYPOPSTACK(1); + yystate = *yyssp; + YY_STACK_PRINT(yyss, yyssp); + } + + if (yyn == YYFINAL) + YYACCEPT; + + *++yyvsp = yylval; + + yyerror_range[1] = yylloc; + /* Using YYLLOC is tempting, but would change the location of + the look-ahead. YYLOC is available though. */ + YYLLOC_DEFAULT(yyloc, (yyerror_range - 1), 2); + *++yylsp = yyloc; + + /* Shift the error token. */ + YY_SYMBOL_PRINT("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror(expr_stack, YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEOF && yychar != YYEMPTY) + yydestruct("Cleanup: discarding lookahead", yytoken, &yylval, &yylloc, expr_stack); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK(yylen); + YY_STACK_PRINT(yyss, yyssp); + while (yyssp != yyss) + { + yydestruct("Cleanup: popping", yystos[*yyssp], yyvsp, yylsp, expr_stack); + YYPOPSTACK(1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE(yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE(yymsg); +#endif + /* Make sure YYID is used. */ + return YYID(yyresult); +} + +#line 77 "parser.y" + +namespace adios2 +{ +namespace detail +{ + +void *createExpr(std::stack *expr_stack, std::string str_op, const char *name, + double value, size_t numsubexprs) +{ + // std::cout << "Creating ASTNode in function createExpr" << std::endl; + // std::cout << "\tstack size: " << expr_stack->size() << "\n\top: " << str_op << "\n\tname: " + // << name << "\n\tvalue: " << value << "\n\tnumsubexprs: " << numsubexprs << std::endl; + + ExpressionOperator op = get_op(str_op); + + ASTNode *node = new ASTNode(op); + switch (op) + { + case ExpressionOperator::OP_ALIAS: + node = new ASTNode(op, name); + break; + case ExpressionOperator::OP_PATH: + node = new ASTNode(op, name); + break; + case ExpressionOperator::OP_NUM: + node = new ASTNode(op, value); + break; + case ExpressionOperator::OP_INDEX: + // TODO: translate indices + node = new ASTNode(op, name); + break; + default: + node = new ASTNode(op); + }; + node->extend_subexprs(numsubexprs); + for (size_t i = 1; i <= numsubexprs; ++i) + { + ASTNode *subexpr = expr_stack->top(); + node->add_back_subexpr(subexpr, i); + expr_stack->pop(); + } + expr_stack->push(node); + + return &expr_stack->top(); +} + +ASTNode *parse_expression(std::string input) +{ + yy_scan_string(input.c_str()); + std::stack expr_stack; + yyparse(&expr_stack); + + // DEBUGGING + // std::cout << "yyparse complete. Stack size: " << expr_stack.size() << std::endl; + // std::cout << "parser prettyprint:" << std::endl; + // expr_stack.top()->printpretty(""); + return expr_stack.top(); +} + +} +} + +void yyerror(std::stack *expr_stack, const char *msg) +{ + printf("** Line %d: %s\n", yylloc.first_line, msg); +} diff --git a/source/adios2/toolkit/derived/parser/parser.h b/source/adios2/toolkit/derived/parser/parser.h new file mode 100644 index 0000000000..38c3c96d58 --- /dev/null +++ b/source/adios2/toolkit/derived/parser/parser.h @@ -0,0 +1,110 @@ +/* A Bison parser, made by GNU Bison 2.3. */ + +/* Skeleton interface for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* Tokens. */ +#ifndef YYTOKENTYPE +#define YYTOKENTYPE +/* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ +enum yytokentype +{ + COMMA = 258, + L_PAREN = 259, + R_PAREN = 260, + ENDL = 261, + FUNCTION = 262, + OPERATOR = 263, + INDICES = 264, + NUMBER = 265, + ALIAS = 266, + PATH = 267 +}; +#endif +/* Tokens. */ +#define COMMA 258 +#define L_PAREN 259 +#define R_PAREN 260 +#define ENDL 261 +#define FUNCTION 262 +#define OPERATOR 263 +#define INDICES 264 +#define NUMBER 265 +#define ALIAS 266 +#define PATH 267 + +#if !defined YYSTYPE && !defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +#line 25 "parser.y" +{ + double dval; + int ival; + char *sval; + void *expr_ptr; +} +/* Line 1529 of yacc.c. */ +#line 80 "parser.h" +YYSTYPE; +#define yystype YYSTYPE /* obsolescent; will be withdrawn */ +#define YYSTYPE_IS_DECLARED 1 +#define YYSTYPE_IS_TRIVIAL 1 +#endif + +extern YYSTYPE yylval; + +#if !defined YYLTYPE && !defined YYLTYPE_IS_DECLARED +typedef struct YYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} YYLTYPE; +#define yyltype YYLTYPE /* obsolescent; will be withdrawn */ +#define YYLTYPE_IS_DECLARED 1 +#define YYLTYPE_IS_TRIVIAL 1 +#endif + +extern YYLTYPE yylloc; + +#include "ASTNode.h" +#include + +namespace adios2 +{ +namespace detail +{ +ASTNode *parse_expression(std::string input); +} +} diff --git a/source/adios2/toolkit/derived/parser/parser.output b/source/adios2/toolkit/derived/parser/parser.output new file mode 100644 index 0000000000..ae7a9b24a1 --- /dev/null +++ b/source/adios2/toolkit/derived/parser/parser.output @@ -0,0 +1,350 @@ +State 5 conflicts: 1 shift/reduce +State 24 conflicts: 1 shift/reduce + + +Grammar + + 0 $accept: input $end + + 1 input: /* empty */ + 2 | ENDL input + 3 | decl input + 4 | exp input + + 5 decl: ALIAS PATH + 6 | ALIAS PATH INDICES + + 7 list: list COMMA exp + 8 | exp + + 9 exp: ALIAS + 10 | ALIAS INDICES + 11 | PATH + 12 | NUMBER + 13 | L_PAREN exp R_PAREN + 14 | exp OPERATOR exp + 15 | FUNCTION L_PAREN list R_PAREN + + +Terminals, with rules where they appear + +$end (0) 0 +error (256) +COMMA (258) 7 +L_PAREN (259) 13 15 +R_PAREN (260) 13 15 +ENDL (261) 2 +FUNCTION (262) 15 +OPERATOR (263) 14 +INDICES (264) 6 10 +NUMBER (265) 12 +ALIAS (266) 5 6 9 10 +PATH (267) 5 6 11 + + +Nonterminals, with rules where they appear + +$accept (13) + on left: 0 +input (14) + on left: 1 2 3 4, on right: 0 2 3 4 +decl (15) + on left: 5 6, on right: 3 +list (16) + on left: 7 8, on right: 7 15 +exp (17) + on left: 9 10 11 12 13 14 15, on right: 4 7 8 13 14 + + +state 0 + + 0 $accept: . input $end + + L_PAREN shift, and go to state 1 + ENDL shift, and go to state 2 + FUNCTION shift, and go to state 3 + NUMBER shift, and go to state 4 + ALIAS shift, and go to state 5 + PATH shift, and go to state 6 + + $default reduce using rule 1 (input) + + input go to state 7 + decl go to state 8 + exp go to state 9 + + +state 1 + + 13 exp: L_PAREN . exp R_PAREN + + L_PAREN shift, and go to state 1 + FUNCTION shift, and go to state 3 + NUMBER shift, and go to state 4 + ALIAS shift, and go to state 10 + PATH shift, and go to state 6 + + exp go to state 11 + + +state 2 + + 2 input: ENDL . input + + L_PAREN shift, and go to state 1 + ENDL shift, and go to state 2 + FUNCTION shift, and go to state 3 + NUMBER shift, and go to state 4 + ALIAS shift, and go to state 5 + PATH shift, and go to state 6 + + $default reduce using rule 1 (input) + + input go to state 12 + decl go to state 8 + exp go to state 9 + + +state 3 + + 15 exp: FUNCTION . L_PAREN list R_PAREN + + L_PAREN shift, and go to state 13 + + +state 4 + + 12 exp: NUMBER . + + $default reduce using rule 12 (exp) + + +state 5 + + 5 decl: ALIAS . PATH + 6 | ALIAS . PATH INDICES + 9 exp: ALIAS . + 10 | ALIAS . INDICES + + INDICES shift, and go to state 14 + PATH shift, and go to state 15 + + PATH [reduce using rule 9 (exp)] + $default reduce using rule 9 (exp) + + +state 6 + + 11 exp: PATH . + + $default reduce using rule 11 (exp) + + +state 7 + + 0 $accept: input . $end + + $end shift, and go to state 16 + + +state 8 + + 3 input: decl . input + + L_PAREN shift, and go to state 1 + ENDL shift, and go to state 2 + FUNCTION shift, and go to state 3 + NUMBER shift, and go to state 4 + ALIAS shift, and go to state 5 + PATH shift, and go to state 6 + + $default reduce using rule 1 (input) + + input go to state 17 + decl go to state 8 + exp go to state 9 + + +state 9 + + 4 input: exp . input + 14 exp: exp . OPERATOR exp + + L_PAREN shift, and go to state 1 + ENDL shift, and go to state 2 + FUNCTION shift, and go to state 3 + OPERATOR shift, and go to state 18 + NUMBER shift, and go to state 4 + ALIAS shift, and go to state 5 + PATH shift, and go to state 6 + + $default reduce using rule 1 (input) + + input go to state 19 + decl go to state 8 + exp go to state 9 + + +state 10 + + 9 exp: ALIAS . + 10 | ALIAS . INDICES + + INDICES shift, and go to state 14 + + $default reduce using rule 9 (exp) + + +state 11 + + 13 exp: L_PAREN exp . R_PAREN + 14 | exp . OPERATOR exp + + R_PAREN shift, and go to state 20 + OPERATOR shift, and go to state 18 + + +state 12 + + 2 input: ENDL input . + + $default reduce using rule 2 (input) + + +state 13 + + 15 exp: FUNCTION L_PAREN . list R_PAREN + + L_PAREN shift, and go to state 1 + FUNCTION shift, and go to state 3 + NUMBER shift, and go to state 4 + ALIAS shift, and go to state 10 + PATH shift, and go to state 6 + + list go to state 21 + exp go to state 22 + + +state 14 + + 10 exp: ALIAS INDICES . + + $default reduce using rule 10 (exp) + + +state 15 + + 5 decl: ALIAS PATH . + 6 | ALIAS PATH . INDICES + + INDICES shift, and go to state 23 + + $default reduce using rule 5 (decl) + + +state 16 + + 0 $accept: input $end . + + $default accept + + +state 17 + + 3 input: decl input . + + $default reduce using rule 3 (input) + + +state 18 + + 14 exp: exp OPERATOR . exp + + L_PAREN shift, and go to state 1 + FUNCTION shift, and go to state 3 + NUMBER shift, and go to state 4 + ALIAS shift, and go to state 10 + PATH shift, and go to state 6 + + exp go to state 24 + + +state 19 + + 4 input: exp input . + + $default reduce using rule 4 (input) + + +state 20 + + 13 exp: L_PAREN exp R_PAREN . + + $default reduce using rule 13 (exp) + + +state 21 + + 7 list: list . COMMA exp + 15 exp: FUNCTION L_PAREN list . R_PAREN + + COMMA shift, and go to state 25 + R_PAREN shift, and go to state 26 + + +state 22 + + 8 list: exp . + 14 exp: exp . OPERATOR exp + + OPERATOR shift, and go to state 18 + + $default reduce using rule 8 (list) + + +state 23 + + 6 decl: ALIAS PATH INDICES . + + $default reduce using rule 6 (decl) + + +state 24 + + 14 exp: exp . OPERATOR exp + 14 | exp OPERATOR exp . + + OPERATOR shift, and go to state 18 + + OPERATOR [reduce using rule 14 (exp)] + $default reduce using rule 14 (exp) + + +state 25 + + 7 list: list COMMA . exp + + L_PAREN shift, and go to state 1 + FUNCTION shift, and go to state 3 + NUMBER shift, and go to state 4 + ALIAS shift, and go to state 10 + PATH shift, and go to state 6 + + exp go to state 27 + + +state 26 + + 15 exp: FUNCTION L_PAREN list R_PAREN . + + $default reduce using rule 15 (exp) + + +state 27 + + 7 list: list COMMA exp . + 14 exp: exp . OPERATOR exp + + OPERATOR shift, and go to state 18 + + $default reduce using rule 7 (list) \ No newline at end of file diff --git a/source/adios2/toolkit/derived/parser/parser.y b/source/adios2/toolkit/derived/parser/parser.y new file mode 100644 index 0000000000..d9bf172459 --- /dev/null +++ b/source/adios2/toolkit/derived/parser/parser.y @@ -0,0 +1,132 @@ +/* calculator. */ +%{ + #include + #include + #include + #include + #include + #include + #include + #include "lexer.h" + #include "ASTNode.h" + + extern int yyparse(std::stack* expr_stack); + + void* createExpr(std::stack*, std::string, const char*, double, size_t); + + static void* yyparse_value; + + void yyerror(std::stack* expr_stack, const char *msg); + +%} + +%parse-param {std::stack* expr_stack} + +%union{ + double dval; + int ival; + char* sval; + void* expr_ptr; +} + +%error-verbose +%locations + +%start input +%token COMMA L_PAREN R_PAREN ENDL +%token FUNCTION +%token OPERATOR +%token INDICES +%token NUMBER +%token ALIAS PATH +%type NUMBER +%type ALIAS PATH INDICES +%type FUNCTION OPERATOR +%type input exp +%type list + + +%% + +input: {} + | ENDL input {} + | decl input {} + | exp input { /*yyparse_value = $1->expression;*/ } + ; + +decl: ALIAS PATH { ASTNode::add_lookup_entry($1, $2, ""); } + | ALIAS PATH INDICES { ASTNode::add_lookup_entry($1, $2, $3); } + ; + +//index: NUMBER comma index { ASTNode::extend_current_lookup_indices($1); } +// | NUMBER { ASTNode::extend_current_lookup_indices($1); } +// ; + +list: list COMMA exp { $$ = $1 +1; } + | exp { $$ = 1;} + ; + +exp: ALIAS { $$ = createExpr(expr_stack, "ALIAS", $1, 0, 0); } +| ALIAS INDICES { createExpr(expr_stack, "ALIAS", $1, 0, 0); $$ = createExpr(expr_stack, "INDEX", $2, 0, 1); } +| PATH { $$ = createExpr(expr_stack, "PATH", $1, 0, 0); } +| NUMBER { $$ = createExpr(expr_stack, "NUM", "", $1, 0); } +| L_PAREN exp R_PAREN { $$ = $2; } +| exp OPERATOR exp { $$ = createExpr(expr_stack, $2, "", 0, 2); } +| FUNCTION L_PAREN list R_PAREN { $$ = createExpr(expr_stack, $1, "", 0, $3); } + ; +%% + +void* createExpr(std::stack* expr_stack, std::string str_op, const char* name, double value, size_t numsubexprs) { + std::cout << "Creating ASTNode in function createExpr" << std::endl; + std::cout << "\tstack size: " << expr_stack->size() << "\n\top: " << str_op << "\n\tname: " << name << "\n\tvalue: " << value << "\n\tnumsubexprs: " << numsubexprs << std::endl; + + ExprHelper::expr_op op = ExprHelper::get_op(str_op); + + ASTNode *node = new ASTNode(op); + switch(op) { + case ExprHelper::OP_ALIAS: + node = new ASTNode(op, name); + break; + case ExprHelper::OP_PATH: + node = new ASTNode(op, name); + break; + case ExprHelper::OP_NUM: + node = new ASTNode(op, value); + break; + case ExprHelper::OP_INDEX: + // TODO: translate indices + node = new ASTNode(op, name); + break; + default: + node = new ASTNode(op); + }; + node->extend_subexprs(numsubexprs); + for (size_t i = 1; i <= numsubexprs; ++i) + { + ASTNode *subexpr = expr_stack->top(); + node->add_back_subexpr(subexpr,i); + expr_stack->pop(); + } + expr_stack->push(node); + + return &expr_stack->top(); +} + +Expression* parse_expression(const char* input) { + yy_scan_string(input); + std::stack expr_stack; + yyparse(&expr_stack); + + // DEBUGGING + std::cout << "yyparse complete. Stack size: " << expr_stack.size() << std::endl; + std::cout << "parser prettyprint:" << std::endl; + expr_stack.top()->printpretty(""); + + Expression *dummy_root = new Expression(); + expr_stack.top()->to_expr(dummy_root); + return std::get<0>(dummy_root->sub_exprs[0]); +} + +void yyerror(std::stack* expr_stack, const char *msg) { + printf("** Line %d: %s\n", yylloc.first_line, msg); +} \ No newline at end of file diff --git a/source/adios2/toolkit/format/bp5/BP5Deserializer.cpp b/source/adios2/toolkit/format/bp5/BP5Deserializer.cpp index cf9fbefc14..6e6ea7e806 100644 --- a/source/adios2/toolkit/format/bp5/BP5Deserializer.cpp +++ b/source/adios2/toolkit/format/bp5/BP5Deserializer.cpp @@ -1,3 +1,4 @@ + /* * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. @@ -238,8 +239,8 @@ void BP5Deserializer::BreakdownArrayName(const char *Name, char **base_name_p, D { /* string formatted as bp5_%d_%d_actualname */ char *p; - // + 3 to skip BP5_ or bp5_ prefix - long n = strtol(Name + 4, &p, 10); + // Prefix has already been skipped + long n = strtol(Name, &p, 10); *element_size_p = static_cast(n); ++p; // skip '_' long Type = strtol(p, &p, 10); @@ -295,6 +296,59 @@ BP5Deserializer::BP5VarRec *BP5Deserializer::CreateVarRec(const char *ArrayName) return Ret; } +/* + * Decode base64 data to 'output'. Decode in-place if 'output' is NULL. + * Return the length of the decoded data, or -1 if there was an error. + */ +static const char signed char_to_num[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, +}; +static int base64_decode(unsigned char *input, unsigned char *output) +{ + int len = 0; + int c1, c2, c3, c4; + + if (output == NULL) + output = input; + while (*input) + { + c1 = *input++; + if (char_to_num[c1] == -1) + return -1; + c2 = *input++; + if (char_to_num[c2] == -1) + return -1; + c3 = *input++; + if (c3 != '=' && char_to_num[c3] == -1) + return -1; + c4 = *input++; + if (c4 != '=' && char_to_num[c4] == -1) + return -1; + *output++ = (char_to_num[c1] << 2) | (char_to_num[c2] >> 4); + ++len; + if (c3 == '=') + break; + *output++ = ((char_to_num[c2] << 4) & 0xf0) | (char_to_num[c3] >> 2); + ++len; + if (c4 == '=') + break; + *output++ = ((char_to_num[c3] << 6) & 0xc0) | char_to_num[c4]; + ++len; + } + + return len; +} + BP5Deserializer::ControlInfo *BP5Deserializer::BuildControl(FMFormat Format) { FMStructDescList FormatList = format_list_of_FMFormat(Format); @@ -312,6 +366,9 @@ BP5Deserializer::ControlInfo *BP5Deserializer::BuildControl(FMFormat Format) size_t VarIndex = 0; while (FieldList[i].field_name) { + size_t HeaderSkip; + char *ExprStr = NULL; + int Derived = 0; ret = (ControlInfo *)realloc(ret, sizeof(*ret) + ControlCount * sizeof(struct ControlInfo)); struct ControlStruct *C = &(ret->Controls[ControlCount]); ControlCount++; @@ -336,6 +393,29 @@ BP5Deserializer::ControlInfo *BP5Deserializer::BuildControl(FMFormat Format) C->OrigShapeID = ShapeID::LocalArray; break; } + if (FieldList[i].field_name[3] == '_') + { + HeaderSkip = 4; + } + else if (FieldList[i].field_name[3] == '-') + { + // Expression follows + Derived = 1; + int EncLen; + int NumberLen; + if (sscanf(&FieldList[i].field_name[4], "%d%n", &EncLen, &NumberLen) == 1) + { // Expression + ExprStr = (char *)malloc(EncLen + 1); + const char *Dash = strchr(&FieldList[i].field_name[4], '-'); + base64_decode((unsigned char *)Dash + 1, (unsigned char *)ExprStr); + HeaderSkip = 6 + NumberLen + EncLen; + } + else + { + fprintf(stderr, "Bad Expression spec in field %s\n", FieldList[i].field_name); + } + } + // BP5VarRec *VarRec = nullptr; if (NameIndicatesArray(FieldList[i].field_name)) { @@ -356,8 +436,8 @@ BP5Deserializer::ControlInfo *BP5Deserializer::BuildControl(FMFormat Format) else { BreakdownFieldType(FieldList[i].field_type, Operator, MinMax); - BreakdownArrayName(FieldList[i].field_name, &ArrayName, &Type, &ElementSize, - &StructFormat); + BreakdownArrayName(FieldList[i].field_name + HeaderSkip, &ArrayName, &Type, + &ElementSize, &StructFormat); } VarRec = LookupVarByName(ArrayName); if (!VarRec) @@ -366,6 +446,8 @@ BP5Deserializer::ControlInfo *BP5Deserializer::BuildControl(FMFormat Format) VarRec->Type = Type; VarRec->ElementSize = ElementSize; VarRec->OrigShapeID = C->OrigShapeID; + VarRec->Derived = Derived; + VarRec->ExprStr = ExprStr; if (StructFormat) { core::StructDefinition *Def = @@ -1501,6 +1583,8 @@ BP5Deserializer::GenerateReadRequests(const bool doAllocTempBuffers, size_t *max RR.Timestep = Req->Step; RR.WriterRank = WriterRank; RR.StartOffset = writer_meta_base->DataBlockLocation[NeededBlock]; + if (RR.StartOffset == (size_t)-1) + throw std::runtime_error("No data exists for this variable"); if (Req->MemSpace != MemorySpace::Host) RR.DirectToAppMemory = false; else @@ -1574,6 +1658,8 @@ BP5Deserializer::GenerateReadRequests(const bool doAllocTempBuffers, size_t *max RR.StartOffset = writer_meta_base->DataBlockLocation[Block]; RR.ReadLength = writer_meta_base->DataBlockSize[Block]; RR.DestinationAddr = nullptr; + if (RR.StartOffset == (size_t)-1) + throw std::runtime_error("No data exists for this variable"); if (doAllocTempBuffers) { RR.DestinationAddr = (char *)malloc(RR.ReadLength); @@ -1611,6 +1697,8 @@ BP5Deserializer::GenerateReadRequests(const bool doAllocTempBuffers, size_t *max RR.WriterRank = WriterRank; RR.StartOffset = writer_meta_base->DataBlockLocation[Block] + StartOffsetInBlock; + if (writer_meta_base->DataBlockLocation[Block] == (size_t)-1) + throw std::runtime_error("No data exists for this variable"); RR.ReadLength = EndOffsetInBlock - StartOffsetInBlock; if (Req->MemSpace != MemorySpace::Host) RR.DirectToAppMemory = false; diff --git a/source/adios2/toolkit/format/bp5/BP5Deserializer.h b/source/adios2/toolkit/format/bp5/BP5Deserializer.h index 3c6aefa355..c2d6f39568 100644 --- a/source/adios2/toolkit/format/bp5/BP5Deserializer.h +++ b/source/adios2/toolkit/format/bp5/BP5Deserializer.h @@ -120,6 +120,8 @@ class BP5Deserializer : virtual public BP5Base size_t JoinedDimen = SIZE_MAX; size_t *LastJoinedOffset = NULL; size_t *LastJoinedShape = NULL; + bool Derived = false; + char *ExprStr = NULL; ShapeID OrigShapeID; core::StructDefinition *Def = nullptr; core::StructDefinition *ReaderDef = nullptr; diff --git a/source/adios2/toolkit/format/bp5/BP5Serializer.cpp b/source/adios2/toolkit/format/bp5/BP5Serializer.cpp index 4bd0140175..d7145bd7fb 100644 --- a/source/adios2/toolkit/format/bp5/BP5Serializer.cpp +++ b/source/adios2/toolkit/format/bp5/BP5Serializer.cpp @@ -10,6 +10,9 @@ #include "adios2/core/Engine.h" #include "adios2/core/IO.h" #include "adios2/core/VariableBase.h" +#ifdef ADIOS2_HAVE_DERIVED_VARIABLE +#include "adios2/core/VariableDerived.h" +#endif #include "adios2/helper/adiosFunctions.h" #include "adios2/toolkit/format/buffer/ffs/BufferFFS.h" @@ -234,25 +237,104 @@ char *BP5Serializer::BuildVarName(const char *base_name, const ShapeID Shape, co return Ret; } +/* + * Do base64 encoding of binary buffer, returning a malloc'd string + */ +static const char num_to_char[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static char *base64_encode(const char *buffer, unsigned int len) +{ + char *buf; + int buflen = 0; + int c1, c2, c3; + int maxlen = len * 4 / 3 + 4; +#ifdef OVERKILL + maxlen = len * 2 + 2; +#endif + + buf = (char *)malloc(maxlen * sizeof(char)); + if (buf == NULL) + { + return NULL; + } + else + { + memset(buf, 0, maxlen * sizeof(char)); + } + + while (len) + { + + c1 = (unsigned char)*buffer++; + buf[buflen++] = num_to_char[c1 >> 2]; + + if (--len == 0) + c2 = 0; + else + c2 = (unsigned char)*buffer++; + buf[buflen++] = num_to_char[((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4)]; + + if (len == 0) + { + buf[buflen++] = '='; + buf[buflen++] = '='; + break; + } + + if (--len == 0) + c3 = 0; + else + c3 = (unsigned char)*buffer++; + + buf[buflen++] = num_to_char[((c2 & 0xf) << 2) | ((c3 & 0xc0) >> 6)]; + if (len == 0) + { + buf[buflen++] = '='; + + break; + } + + --len; + buf[buflen++] = num_to_char[c3 & 0x3f]; + } + + buf[buflen] = 0; + + return buf; +} + static char *BuildLongName(const char *base_name, const ShapeID Shape, const int type, - const size_t element_size, const char *StructID) + const size_t element_size, const char *StructID, const char *ExprStr) { const char *Prefix = NamePrefix(Shape); size_t StructIDLen = 0; + size_t ExprLen = 0; + char *ExpressionInsert = (char *)"_"; if (StructID) StructIDLen = strlen(StructID); - size_t Len = strlen(base_name) + 3 + strlen(Prefix) + StructIDLen + 16; + if (ExprStr) + { + char *ExprEnc = base64_encode(ExprStr, (int)(strlen(ExprStr) + 1)); + ExprLen = strlen(ExprEnc); + ExpressionInsert = (char *)malloc(ExprLen + 16); // str + enough for len and separators + snprintf(ExpressionInsert, ExprLen + 16, "-%zu-%s-", ExprLen, ExprEnc); + free(ExprEnc); + } + size_t Len = strlen(base_name) + 3 + ExprLen + strlen(Prefix) + StructIDLen + 16; char *Ret = (char *)malloc(Len); if (StructID) { - snprintf(Ret, Len, "%s_%zd_%d_%s", Prefix, element_size, type, StructID); + snprintf(Ret, Len, "%s%s%zd_%d_%s", Prefix, ExpressionInsert, element_size, type, StructID); } else { - snprintf(Ret, Len, "%s_%zd_%d", Prefix, element_size, type); + snprintf(Ret, Len, "%s%s%zd_%d", Prefix, ExpressionInsert, element_size, type); } strcat(Ret, "_"); strcat(Ret, base_name); + if (ExprStr) + free(ExpressionInsert); return Ret; } @@ -420,6 +502,9 @@ BP5Serializer::BP5WriterRec BP5Serializer::CreateWriterRec(void *Variable, const size_t DimCount) { core::VariableBase *VB = static_cast(Variable); +#ifdef ADIOS2_HAVE_DERIVED_VARIABLE + core::VariableDerived *VD = dynamic_cast(VB); +#endif auto obj = Info.RecMap.insert(std::make_pair(Variable, _BP5WriterRec())); BP5WriterRec Rec = &obj.first->second; if (Type == DataType::String) @@ -497,7 +582,12 @@ BP5Serializer::BP5WriterRec BP5Serializer::CreateWriterRec(void *Variable, const } // Array field. To Metadata, add FMFields for DimCount, Shape, Count // and Offsets matching _MetaArrayRec - char *LongName = BuildLongName(Name, VB->m_ShapeID, (int)Type, ElemSize, TextStructID); + const char *ExprString = NULL; +#ifdef ADIOS2_HAVE_DERIVED_VARIABLE + ExprString = VD ? VD->m_Expr.ExprString.c_str() : NULL; +#endif + char *LongName = + BuildLongName(Name, VB->m_ShapeID, (int)Type, ElemSize, TextStructID, ExprString); const char *ArrayTypeName = "MetaArray"; int FieldSize = sizeof(MetaArrayRec); @@ -643,7 +733,18 @@ void BP5Serializer::Marshal(void *Variable, const char *Name, const DataType Typ }; core::VariableBase *VB = static_cast(Variable); +#ifdef ADIOS2_HAVE_DERIVED_VARIABLE + core::VariableDerived *VD = dynamic_cast(VB); +#endif + bool WriteData = true; +#ifdef ADIOS2_HAVE_DERIVED_VARIABLE + if (VD) + { + // All other types of Derived types we don't write data + WriteData = (VD->GetDerivedType() == DerivedVarType::StoreData); + } +#endif BP5MetadataInfoStruct *MBase; BP5WriterRec Rec = LookupWriterRec(Variable); @@ -714,7 +815,12 @@ void BP5Serializer::Marshal(void *Variable, const char *Name, const DataType Typ MinMaxStruct MinMax; MinMax.Init(Type); - if ((m_StatsLevel > 0) && !Span) + bool DerivedWithoutStats = false; +#ifdef ADIOS2_HAVE_DERIVED_VARIABLE + DerivedWithoutStats = VD && (VD->GetDerivedType() == DerivedVarType::ExpressionString); +#endif + bool DoMinMax = ((m_StatsLevel > 0) && !DerivedWithoutStats); + if (DoMinMax && !Span) { GetMinMax(Data, ElemCount, (DataType)Rec->Type, MinMax, MemSpace); } @@ -744,6 +850,11 @@ void BP5Serializer::Marshal(void *Variable, const char *Name, const DataType Typ VB->m_Operations[0]->GetHeaderSize(), MemSpace); CurDataBuffer->DownsizeLastAlloc(AllocSize, CompressedSize); } + else if (!WriteData) + { + DataOffset = (size_t)-1; + DeferAddToVec = false; + } else if (Span == nullptr) { if (!DeferAddToVec) @@ -781,7 +892,7 @@ void BP5Serializer::Marshal(void *Variable, const char *Name, const DataType Typ MetaEntry->Offsets = CopyDims(DimCount, Offsets); else MetaEntry->Offsets = NULL; - if (m_StatsLevel > 0) + if (DoMinMax) { void **MMPtrLoc = (void **)(((char *)MetaEntry) + Rec->MinMaxOffset); *MMPtrLoc = (void *)malloc(ElemSize * 2); @@ -823,7 +934,7 @@ void BP5Serializer::Marshal(void *Variable, const char *Name, const DataType Typ (size_t *)realloc(OpEntry->DataBlockSize, OpEntry->BlockCount * sizeof(size_t)); OpEntry->DataBlockSize[OpEntry->BlockCount - 1] = CompressedSize; } - if (m_StatsLevel > 0) + if (DoMinMax) { void **MMPtrLoc = (void **)(((char *)MetaEntry) + Rec->MinMaxOffset); *MMPtrLoc = (void *)realloc(*MMPtrLoc, MetaEntry->BlockCount * ElemSize * 2); @@ -854,6 +965,18 @@ void BP5Serializer::Marshal(void *Variable, const char *Name, const DataType Typ } } +const void *BP5Serializer::SearchDeferredBlocks(size_t MetaOffset, size_t BlockID) +{ + for (auto &Def : DeferredExterns) + { + if ((Def.MetaOffset == MetaOffset) && (Def.BlockID == BlockID)) + { + return Def.Data; + } + } + return NULL; +} + MinVarInfo *BP5Serializer::MinBlocksInfo(const core::VariableBase &Var) { BP5WriterRec VarRec = LookupWriterRec((void *)&Var); @@ -912,8 +1035,10 @@ MinVarInfo *BP5Serializer::MinBlocksInfo(const core::VariableBase &Var) } else { - Blk.BufferP = CurDataBuffer->GetPtr(MetaEntry->DataBlockLocation[b] - - m_PriorDataBufferSizeTotal); + Blk.BufferP = (void *)SearchDeferredBlocks(VarRec->MetaOffset, b); + if (!Blk.BufferP) + Blk.BufferP = CurDataBuffer->GetPtr(MetaEntry->DataBlockLocation[b] - + m_PriorDataBufferSizeTotal); } MV->BlocksInfo.push_back(Blk); } diff --git a/source/adios2/toolkit/format/bp5/BP5Serializer.h b/source/adios2/toolkit/format/bp5/BP5Serializer.h index 94025f1b2b..d07aa727fa 100644 --- a/source/adios2/toolkit/format/bp5/BP5Serializer.h +++ b/source/adios2/toolkit/format/bp5/BP5Serializer.h @@ -244,6 +244,9 @@ class BP5Serializer : virtual public BP5Base size_t ElemCount; void *Array; } ArrayRec; + +private: + const void *SearchDeferredBlocks(size_t MetaOffset, size_t blocknum); }; } // end namespace format diff --git a/testing/adios2/CMakeLists.txt b/testing/adios2/CMakeLists.txt index bddb8485f4..dc1ede6bca 100644 --- a/testing/adios2/CMakeLists.txt +++ b/testing/adios2/CMakeLists.txt @@ -13,3 +13,6 @@ add_subdirectory(performance) add_subdirectory(helper) add_subdirectory(hierarchy) add_subdirectory(backward_compatibility) +if (ADIOS2_HAVE_Derived_Variable) +add_subdirectory(derived) +endif() diff --git a/testing/adios2/derived/CMakeLists.txt b/testing/adios2/derived/CMakeLists.txt new file mode 100644 index 0000000000..2df2938853 --- /dev/null +++ b/testing/adios2/derived/CMakeLists.txt @@ -0,0 +1,6 @@ +#------------------------------------------------------------------------------# +#Distributed under the OSI - approved Apache License, Version 2.0. See +#accompanying file Copyright.txt for details. +#------------------------------------------------------------------------------# + +gtest_add_tests_helper(DerivedCorrectness MPI_ALLOW BP Derived. "") diff --git a/testing/adios2/derived/TestBPDerivedCorrectness.cpp b/testing/adios2/derived/TestBPDerivedCorrectness.cpp new file mode 100644 index 0000000000..002015b843 --- /dev/null +++ b/testing/adios2/derived/TestBPDerivedCorrectness.cpp @@ -0,0 +1,183 @@ +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +TEST(DerivedCorrectness, AddCorrectnessTest) +{ + const size_t Nx = 10, Ny = 3, Nz = 6; + const size_t steps = 2; + /** Application variable */ + std::default_random_engine generator; + std::uniform_real_distribution distribution(0.0, 10.0); + + std::vector simArray1(Nx * Ny * Nz); + std::vector simArray2(Nx * Ny * Nz); + std::vector simArray3(Nx * Ny * Nz); + for (size_t i = 0; i < Nx * Ny * Nz; ++i) + { + simArray1[i] = distribution(generator); + simArray2[i] = distribution(generator); + simArray3[i] = distribution(generator); + } + + adios2::ADIOS adios; + + adios2::IO bpOut = adios.DeclareIO("BPWriteAddExpression"); + + std::vector varname = {"sim1/Ux", "sim1/Uy", "sim1/Uz"}; + std::string derivedname = "derived/addU"; + + std::cout << "Define Variable " << varname[0] << std::endl; + auto Ux = bpOut.DefineVariable(varname[0], {Nx, Ny, Nz}, {0, 0, 0}, {Nx, Ny, Nz}); + std::cout << "Define Variable " << varname[1] << std::endl; + auto Uy = bpOut.DefineVariable(varname[1], {Nx, Ny, Nz}, {0, 0, 0}, {Nx, Ny, Nz}); + std::cout << "Define Variable " << varname[2] << std::endl; + auto Uz = bpOut.DefineVariable(varname[2], {Nx, Ny, Nz}, {0, 0, 0}, {Nx, Ny, Nz}); + std::cout << "Define Derived Variable " << derivedname << std::endl; + // clang-format off + auto addU = bpOut.DefineDerivedVariable(derivedname, + "x:" + varname[0] + " \n" + "y:" + varname[1] + " \n" + "z:" + varname[2] + " \n" + "x+y+z", + adios2::DerivedVarType::StoreData); + // clang-format on + std::string filename = "expAdd.bp"; + adios2::Engine bpFileWriter = bpOut.Open(filename, adios2::Mode::Write); + + for (int i = 0; i < steps; i++) + { + bpFileWriter.BeginStep(); + bpFileWriter.Put(Ux, simArray1.data()); + bpFileWriter.Put(Uy, simArray2.data()); + bpFileWriter.Put(Uz, simArray3.data()); + bpFileWriter.EndStep(); + } + bpFileWriter.Close(); + + adios2::IO bpIn = adios.DeclareIO("BPReadExpression"); + adios2::Engine bpFileReader = bpIn.Open(filename, adios2::Mode::Read); + + std::vector readUx; + std::vector readUy; + std::vector readUz; + std::vector readAdd; + + float calcA; + float epsilon = 0.01; + for (int i = 0; i < steps; i++) + { + bpFileReader.BeginStep(); + bpFileReader.Get(varname[0], readUx); + bpFileReader.Get(varname[1], readUy); + bpFileReader.Get(varname[2], readUz); + bpFileReader.Get(derivedname, readAdd); + bpFileReader.EndStep(); + + for (size_t ind = 0; ind < Nx * Ny * Nz; ++ind) + { + calcA = readUx[ind] + readUy[ind] + readUz[ind]; + EXPECT_TRUE(fabs(calcA - readAdd[ind]) < epsilon); + } + } + bpFileReader.Close(); +} + +TEST(DerivedCorrectness, MagCorrectnessTest) +{ + const size_t Nx = 2, Ny = 3, Nz = 10; + const size_t steps = 2; + // Application variable + std::default_random_engine generator; + std::uniform_real_distribution distribution(0.0, 10.0); + + std::vector simArray1(Nx * Ny * Nz); + std::vector simArray2(Nx * Ny * Nz); + std::vector simArray3(Nx * Ny * Nz); + for (size_t i = 0; i < Nx * Ny * Nz; ++i) + { + simArray1[i] = distribution(generator); + simArray2[i] = distribution(generator); + simArray3[i] = distribution(generator); + } + + adios2::ADIOS adios; + adios2::IO bpOut = adios.DeclareIO("BPWriteExpression"); + std::vector varname = {"sim2/Ux", "sim2/Uy", "sim2/Uz"}; + std::string derivedname = "derived/magU"; + + auto Ux = bpOut.DefineVariable(varname[0], {Nx, Ny, Nz}, {0, 0, 0}, {Nx, Ny, Nz}); + auto Uy = bpOut.DefineVariable(varname[1], {Nx, Ny, Nz}, {0, 0, 0}, {Nx, Ny, Nz}); + auto Uz = bpOut.DefineVariable(varname[2], {Nx, Ny, Nz}, {0, 0, 0}, {Nx, Ny, Nz}); + // clang-format off + auto magU = bpOut.DefineDerivedVariable(derivedname, + "x:" + varname[0] + " \n" + "y:" + varname[1] + " \n" + "z:" + varname[2] + " \n" + "magnitude(x,y,z)", + adios2::DerivedVarType::StoreData); + // clang-format on + std::string filename = "expMagnitude.bp"; + adios2::Engine bpFileWriter = bpOut.Open(filename, adios2::Mode::Write); + + for (int i = 0; i < steps; i++) + { + bpFileWriter.BeginStep(); + bpFileWriter.Put(Ux, simArray1.data()); + bpFileWriter.Put(Uy, simArray2.data()); + bpFileWriter.Put(Uz, simArray3.data()); + bpFileWriter.EndStep(); + } + bpFileWriter.Close(); + + adios2::IO bpIn = adios.DeclareIO("BPReadMagExpression"); + adios2::Engine bpFileReader = bpIn.Open(filename, adios2::Mode::Read); + + std::vector readUx; + std::vector readUy; + std::vector readUz; + std::vector readMag; + + float calcM; + float epsilon = 0.01; + for (int i = 0; i < steps; i++) + { + bpFileReader.BeginStep(); + auto varx = bpIn.InquireVariable(varname[0]); + auto vary = bpIn.InquireVariable(varname[1]); + auto varz = bpIn.InquireVariable(varname[2]); + auto varmag = bpIn.InquireVariable(derivedname); + + bpFileReader.Get(varx, readUx); + bpFileReader.Get(vary, readUy); + bpFileReader.Get(varz, readUz); + bpFileReader.Get(varmag, readMag); + bpFileReader.EndStep(); + + for (size_t ind = 0; ind < Nx * Ny * Nz; ++ind) + { + calcM = sqrt(pow(readUx[ind], 2) + pow(readUy[ind], 2) + pow(readUz[ind], 2)); + EXPECT_TRUE(fabs(calcM - readMag[ind]) < epsilon); + } + } + bpFileReader.Close(); +} + +int main(int argc, char **argv) +{ + int result; + ::testing::InitGoogleTest(&argc, argv); + + result = RUN_ALL_TESTS(); + + return result; +}