Commit 1bbe5cc5 authored by Pierre Aubert's avatar Pierre Aubert
Browse files

Fix the parsing of PStmt with operators and with respect to the operator priority

parent 40654057
Pipeline #99354 passed with stages
in 11 minutes and 1 second
...@@ -14,4 +14,5 @@ add_subdirectory(TEST_C_ENUM) ...@@ -14,4 +14,5 @@ add_subdirectory(TEST_C_ENUM)
add_subdirectory(TEST_VAR_DECL) add_subdirectory(TEST_VAR_DECL)
add_subdirectory(TEST_VAR_DECL_STRING) add_subdirectory(TEST_VAR_DECL_STRING)
add_subdirectory(TEST_OPERATOR) add_subdirectory(TEST_OPERATOR)
add_subdirectory(TEST_OPERATOR_PRIORITY)
project(Phoenix)
cmake_minimum_required(VERSION 3.0)
# compileLibTestGenerator(test_math_operator_priority_parser "PTestOperatorParser" parser_operator.pdecparser)
# compileMainTestGenerator(test_math_operator_priority_parser "PTestOperatorParser" parser_operator.pdecparser main_test.cpp)
# Only when the test will be OK
# compileTestGenerator(test_math_operator_priority_parser "PTestOperatorParser" parser_operator.pdecparser main_test.cpp fileAdd.math)
compileBaseTestGenerator(test_math_operator_priority_parser "PTestOperatorParser" parser_operator.pdecparser main_base_test.cpp)
add_executable(test_math_operator_priority_parser_input main_test.cpp)
target_link_libraries(test_math_operator_priority_parser_input test_math_operator_priority_parser_parser phoenix_parser_stmt file_parser option_parser string_utils)
add_test(NAME Test_test_math_operator_priority_parser_input
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_math_operator_priority_parser_input -i ${CMAKE_CURRENT_SOURCE_DIR}/fileAdd.math -r "(a+b)"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
add_test(NAME Test_test_math_operator_priority_parser_input3
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_math_operator_priority_parser_input -i ${CMAKE_CURRENT_SOURCE_DIR}/fileAdd3.math -r "(a+(b+c))"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
add_test(NAME Test_test_math_operator_priority_parser_inputMult
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_math_operator_priority_parser_input -i ${CMAKE_CURRENT_SOURCE_DIR}/fileMult.math -r "(a*b)"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
add_test(NAME Test_test_math_operator_priority_parser_inputMult3
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_math_operator_priority_parser_input -i ${CMAKE_CURRENT_SOURCE_DIR}/fileMult3.math -r "(a*(b*c))"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
add_test(NAME Test_test_math_operator_priority_parser_inputMultAdd
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_math_operator_priority_parser_input -i ${CMAKE_CURRENT_SOURCE_DIR}/fileMultAdd.math -r "((a*b)+c)"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
add_test(NAME Test_test_math_operator_priority_parser_inputAddMult
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_math_operator_priority_parser_input -i ${CMAKE_CURRENT_SOURCE_DIR}/fileAddMult.math -r "(a+(b*c))"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
/***************************************
Auteur : Pierre Aubert
Mail : aubertp7@gmail.com
Licence : CeCILL-C
****************************************/
// To get the generated parser
#include "PTestOperatorParserFull.h"
using namespace std;
///Test the conversion of and add expression into a string
/** @return true on success, false otherwise
*/
bool testExprAddToString(){
PExpr varA = PExpr_default();
PExpr_setType(varA, PExprType::VAR);
PExpr_setVarName(varA, "a");
PExpr varB = PExpr_default();
PExpr_setType(varB, PExprType::VAR);
PExpr_setVarName(varB, "b");
PExpr exprAdd = PExpr_default();
PExpr_setType(exprAdd, PExprType::ADD);
PExpr_getVecOperand(exprAdd).push_back(varA);
PExpr_getVecOperand(exprAdd).push_back(varB);
std::string exprStr = gExprVarName(exprAdd);
std::cout << "testExprAddToString : exprAdd = '"<<exprStr<<"'" << std::endl;
// std::cout << "testExprAddToString : exprAdd ok example :"<< std::endl;
// exprAdd.print();
return exprStr == "(a+b)";
}
///Test the conversion of and add expression into a string
/** @return true on success, false otherwise
*/
bool testExprAdd2ToString(){
PExpr varA = PExpr_default();
PExpr_setType(varA, PExprType::VAR);
PExpr_setVarName(varA, "a");
PExpr varB = PExpr_default();
PExpr_setType(varB, PExprType::VAR);
PExpr_setVarName(varB, "b");
PExpr exprAddAB = PExpr_default();
PExpr_setType(exprAddAB, PExprType::ADD);
PExpr_getVecOperand(exprAddAB).push_back(varA);
PExpr_getVecOperand(exprAddAB).push_back(varB);
PExpr varC = PExpr_default();
PExpr_setType(varC, PExprType::VAR);
PExpr_setVarName(varC, "c");
PExpr exprAdd = PExpr_default();
PExpr_setType(exprAdd, PExprType::ADD);
PExpr_getVecOperand(exprAdd).push_back(exprAddAB);
PExpr_getVecOperand(exprAdd).push_back(varC);
std::string exprStr = gExprVarName(exprAdd);
std::cout << "testExprAdd2ToString : exprAdd = '"<<exprStr<<"'" << std::endl;
return exprStr == "((a+b)+c)";
}
///Test the conversion of and add expression into a string
/** @return true on success, false otherwise
*/
bool testExprAdd3ToString(){
PExpr varA = PExpr_default();
PExpr_setType(varA, PExprType::VAR);
PExpr_setVarName(varA, "a");
PExpr varB = PExpr_default();
PExpr_setType(varB, PExprType::VAR);
PExpr_setVarName(varB, "b");
PExpr exprAddAB = PExpr_default();
PExpr_setType(exprAddAB, PExprType::ADD);
PExpr_getVecOperand(exprAddAB).push_back(varA);
PExpr_getVecOperand(exprAddAB).push_back(varB);
PExpr varC = PExpr_default();
PExpr_setType(varC, PExprType::VAR);
PExpr_setVarName(varC, "c");
PExpr varD = PExpr_default();
PExpr_setType(varD, PExprType::VAR);
PExpr_setVarName(varD, "d");
PExpr exprAddCD = PExpr_default();
PExpr_setType(exprAddCD, PExprType::ADD);
PExpr_getVecOperand(exprAddCD).push_back(varC);
PExpr_getVecOperand(exprAddCD).push_back(varD);
PExpr exprAdd = PExpr_default();
PExpr_setType(exprAdd, PExprType::ADD);
PExpr_getVecOperand(exprAdd).push_back(exprAddAB);
PExpr_getVecOperand(exprAdd).push_back(exprAddCD);
std::string exprStr = gExprVarName(exprAdd);
std::cout << "testExprAdd3ToString : exprAdd = '"<<exprStr<<"'" << std::endl;
return exprStr == "((a+b)+(c+d))";
}
int main(int argc, char** argv){
bool b(testExprAddToString());
b &= testExprAdd2ToString();
b &= testExprAdd3ToString();
if(b){return 0;}
else{return -1;}
}
/***************************************
Auteur : Pierre Aubert
Mail : aubertp7@gmail.com
Licence : CeCILL-C
****************************************/
#include "OptionParser.h"
// To get the generated parser
#include "PTestOperatorParserFull.h"
using namespace std;
///Create the OptionParser of this program
/** @return OptionParser of this program
*/
OptionParser createOptionParser(){
OptionParser parser(true, __PROGRAM_VERSION__);
parser.setExampleLongOption("use_parser --input=fileName.shadok");
parser.setExampleShortOption("use_parser -i fileName.shadok");
parser.addOption("input", "i", OptionType::FILENAME, true, "input code file name");
parser.addOption("reference", "r", OptionType::STRING, true, "reference value to be parsed");
return parser;
}
///Parse a source file
/** @param fileName : name of the source file
* @param reference : expeced result of the parsed file
* @return true on success, false otherwise
*/
bool testParseFileName(const std::string & fileName, const std::string & reference){
//We create the parser
PTestOperatorParser parser;
if(!parser.load(fileName)){
cerr << "testParseFileName : can't load file '"<<fileName<<"'" << endl;
return false;
}
//We get the parsed internal representation
PExpr & source = parser.getPExprE();
std::cout << "PExpr full stmt :" << std::endl;
source.print();
std::string exprStr = gExprVarName(source);
std::cout << "testParseFileName : exprStr = '"<<exprStr<<"', expected = '"<<reference<<"'" << std::endl;
return exprStr == reference;
}
int main(int argc, char** argv){
OptionParser optionParser = createOptionParser();
optionParser.parseArgument(argc, argv);
const OptionMode & defaultMode = optionParser.getDefaultMode();
std::string fileName(""), reference("");
defaultMode.getValue(fileName, "input");
defaultMode.getValue(reference, "reference");
bool b(true);
b &= testParseFileName(fileName, reference);
if(b){return 0;}
else{return -1;}
}
///Type of the expression
Enum PExprType{
VAR
ADD
MULT
};
///Describes a simple mathematic expression
Class PExpr{
///Type of the expression
PExprType::PExprType type;
///Name of the variable
String varName[csVariableName];
///Vector of operand
Vector(PExpr) vecOperand;
}
Graph gExprVarName(PExpr e){
e.varName e.type=PExprType::VAR
}
Operator("+", PExpr, type=PExprType::ADD, vecOperand, gExprVarName, gExprVarName)
Operator("*", PExpr, type=PExprType::MULT, vecOperand, gExprVarName, gExprVarName)
...@@ -61,6 +61,7 @@ std::string repr_cpp_operatorHeader(const PTabGraphToken & tabGraphToken){ ...@@ -61,6 +61,7 @@ std::string repr_cpp_operatorHeader(const PTabGraphToken & tabGraphToken){
body += "bool isAnOperator(const PStmt & _op);\n"; body += "bool isAnOperator(const PStmt & _op);\n";
body += "long get_priority_operator(const PStmt & _op);\n"; body += "long get_priority_operator(const PStmt & _op);\n";
body += "PStmt* get_last_operand_of_operator(PStmt & _op);\n"; body += "PStmt* get_last_operand_of_operator(PStmt & _op);\n";
body += "PStmt* get_first_operand_of_operator(PStmt & _op);\n";
body += "\n\n"; body += "\n\n";
body += "#endif\n\n\n"; body += "#endif\n\n\n";
...@@ -127,7 +128,7 @@ std::string repr_cpp_operatorSource(const PTabGraphToken & tabGraphToken, const ...@@ -127,7 +128,7 @@ std::string repr_cpp_operatorSource(const PTabGraphToken & tabGraphToken, const
body += "*/\n"; body += "*/\n";
body += "PStmt* get_last_operand_of_operator(PStmt & _op){\n"; body += "PStmt* get_last_operand_of_operator(PStmt & _op){\n";
body += "\t//repr_cpp_operator : Get the last operand of the given operator\n"; body += "\t//repr_cpp_operator : Get the last operand of the given operator\n";
body += "\tPStmt * outputPtr = NULL;\n"; body += "\tPStmt * outputPtr = &_op;\n";
prevElse = ""; prevElse = "";
for(PMapVecOperator::iterator itVec(mapOp.begin()); itVec != mapOp.end(); ++itVec){ for(PMapVecOperator::iterator itVec(mapOp.begin()); itVec != mapOp.end(); ++itVec){
body += "\t"+prevElse+"if(is"+(itVec->first)+"(_op)){\n"; body += "\t"+prevElse+"if(is"+(itVec->first)+"(_op)){\n";
...@@ -136,7 +137,32 @@ std::string repr_cpp_operatorSource(const PTabGraphToken & tabGraphToken, const ...@@ -136,7 +137,32 @@ std::string repr_cpp_operatorSource(const PTabGraphToken & tabGraphToken, const
body += "\t\t"+itPrevElse+"if("+it->getExprClass()+"_get"+firstToUpper(it->getAttrEnum())+"(_op) == "+it->getValueEnum()+"){\n"; body += "\t\t"+itPrevElse+"if("+it->getExprClass()+"_get"+firstToUpper(it->getAttrEnum())+"(_op) == "+it->getValueEnum()+"){\n";
body += "\t\t\t//repr_cpp_operator : let's get the number of operand of this operator\n"; body += "\t\t\t//repr_cpp_operator : let's get the number of operand of this operator\n";
body += "\t\t\tPStmt & vecOp = "+it->getExprClass()+"_get"+firstToUpper(it->getVecOp())+"(_op);\n"; body += "\t\t\tPStmt & vecOp = "+it->getExprClass()+"_get"+firstToUpper(it->getVecOp())+"(_op);\n";
body += "\t\t\tif(vecOp.size() != 0lu){outputPtr = &(vecOp.back());}\n"; body += "\t\t\tif(vecOp.size() != 0lu){outputPtr = get_last_operand_of_operator(vecOp.back());}\n";
body += "\t\t}\n";
itPrevElse = "else ";
}
body += "\t}";
prevElse = "else ";
}
body += "\n\treturn outputPtr;\n";
body += "}\n\n";
body += "///Get the first operand of the given PStmt\n";
body += "/**\t@param _op : expression to be checked\n";
body += " * \t@return pointer to the first operand of the given operator, NULL otherwise\n";
body += "*/\n";
body += "PStmt* get_first_operand_of_operator(PStmt & _op){\n";
body += "\t//repr_cpp_operator : Get the first operand of the given operator\n";
body += "\tPStmt * outputPtr = &_op;\n";
prevElse = "";
for(PMapVecOperator::iterator itVec(mapOp.begin()); itVec != mapOp.end(); ++itVec){
body += "\t"+prevElse+"if(is"+(itVec->first)+"(_op)){\n";
std::string itPrevElse("");
for(PVecOperator::iterator it(itVec->second.begin()); it != itVec->second.end(); ++it){
body += "\t\t"+itPrevElse+"if("+it->getExprClass()+"_get"+firstToUpper(it->getAttrEnum())+"(_op) == "+it->getValueEnum()+"){\n";
body += "\t\t\t//repr_cpp_operator : let's get the number of operand of this operator\n";
body += "\t\t\tPStmt & vecOp = "+it->getExprClass()+"_get"+firstToUpper(it->getVecOp())+"(_op);\n";
body += "\t\t\tif(vecOp.size() != 0lu){outputPtr = get_last_operand_of_operator(vecOp.front());}\n";
body += "\t\t}\n"; body += "\t\t}\n";
itPrevElse = "else "; itPrevElse = "else ";
} }
......
...@@ -34,12 +34,13 @@ std::string repr_cpp_tokenOperatorHeader(const PTabGraphToken & tabGraphToken, c ...@@ -34,12 +34,13 @@ std::string repr_cpp_tokenOperatorHeader(const PTabGraphToken & tabGraphToken, c
*/ */
std::string repr_cpp_singleTokenOperator(const POperator & op, const PGraphToken & graphToken){ std::string repr_cpp_singleTokenOperator(const POperator & op, const PGraphToken & graphToken){
std::string body(""), name(graphToken.getName()), varName(graphToken.getVarName()), varType(graphToken.getVarType()); std::string body(""), name(graphToken.getName()), varName(graphToken.getVarName()), varType(graphToken.getVarType());
std::string opToken(op.getVecToken().front());
body += "\t//repr_cpp_token_operator : Let's parse an Operator with 1 token\n"; body += "\t//repr_cpp_token_operator : Let's parse an Operator with 1 token\n";
body += "\t//repr_cpp_token_operator : the first operand is already parsed and given as parameter\n"; body += "\t//repr_cpp_token_operator : the first operand is already parsed and given as parameter\n";
body += "\t//repr_cpp_token_operator : it would be great to add a while\n\n"; body += "\t//repr_cpp_token_operator : it would be great to add a while\n\n";
body += "\tif(!isMatch(\""+op.getVecToken().front()+"\")){return false;}\n"; body += "\tif(!isMatch(\""+opToken+"\")){return false;}\n";
body += "\t//repr_cpp_token_operator : Let's call the graph token of the second operand\n"; body += "\t//repr_cpp_token_operator : Let's call the graph token of the second operand\n";
...@@ -54,19 +55,22 @@ std::string repr_cpp_singleTokenOperator(const POperator & op, const PGraphToken ...@@ -54,19 +55,22 @@ std::string repr_cpp_singleTokenOperator(const POperator & op, const PGraphToken
body += "\tPStmt & vecOperand = "+op.getExprClass()+"_get"+firstToUpper(op.getVecOp())+"(op);\n"; body += "\tPStmt & vecOperand = "+op.getExprClass()+"_get"+firstToUpper(op.getVecOp())+"(op);\n";
body += "\t\n"; body += "\t\n";
body += "\tbool isStandardPushBack(true);\n"; body += "\tbool isStandardPushBack(true);\n";
body += "\tif(isAnOperator(e)){\n"; body += "\tif(isAnOperator(rightOp)){\n";
body += "\t\tlong priorityOp(get_priority_operator(op)), priorityInput(get_priority_operator("+varName+"));\n"; body += "\t\tlong priorityOp(get_priority_operator(op)), priorityRight(get_priority_operator(rightOp));\n";
body += "\t\tif(priorityOp > priorityInput){\n"; body += "\t\tstd::cout << \"op '"+opToken+"' : priorityOp = \" << priorityOp << \", priorityRight = \" << priorityRight << std::endl;\n";
body += "\t\t\t//repr_cpp_token_operator : Let's get the last operand of the input "+varName+"\n"; body += "\t\tif(priorityOp > priorityRight){\n";
body += "\t\t\tPStmt * lastOp = get_last_operand_of_operator("+varName+");\n"; body += "\t\t\t//repr_cpp_token_operator : Let's get the first operand of the right operator rightOp\n";
body += "\t\t\tvecOperand.push_back(*lastOp);\t//This is a copy, so it works\n"; body += "\t\t\tPStmt * firstOp = get_first_operand_of_operator(rightOp);\n";
body += "\t\t\tvecOperand.push_back(rightOp);\n"; body += "\t\t\tif(firstOp == NULL){return NULL;}\n";
body += "\t\t\t*lastOp = op;\n"; body += "\t\t\tvecOperand.push_back("+varName+");\t//This is a copy, so it works\n";
body += "\t\t\t\n"; body += "\t\t\tvecOperand.push_back(*firstOp);\n";
body += "\t\t\t*firstOp = op;\n";
body += "\t\t\t"+varName+" = rightOp;\n";
body += "\t\t\tisStandardPushBack = false;\n"; body += "\t\t\tisStandardPushBack = false;\n";
body += "\t\t}\n"; body += "\t\t}\n";
body += "\t}\n"; body += "\t}\n";
body += "\tif(isStandardPushBack){\n"; body += "\tif(isStandardPushBack){\n";
body += "\t\tstd::cout << \"op '"+opToken+"' : Do a standard push_back\" << std::endl;\n";
body += "\t\tvecOperand.push_back("+varName+");\n"; body += "\t\tvecOperand.push_back("+varName+");\n";
body += "\t\tvecOperand.push_back(rightOp);\n"; body += "\t\tvecOperand.push_back(rightOp);\n";
body += "\t\t//repr_cpp_token_operator : Finally, put the operator in the in/out parameter\n"; body += "\t\t//repr_cpp_token_operator : Finally, put the operator in the in/out parameter\n";
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment