Merge lp:~tapaal-dist-ctl/verifypn/arithmeticExpressions into lp:verifypn

Proposed by Søren Moss Nielsen
Status: Superseded
Proposed branch: lp:~tapaal-dist-ctl/verifypn/arithmeticExpressions
Merge into: lp:verifypn
Diff against target: 410 lines (+197/-40)
7 files modified
CTL/CTLParser/CTLParser.cpp (+31/-7)
CTL/CTLParser/CTLQuery.cpp (+4/-4)
CTL/CTLParser/EvaluateableProposition.cpp (+129/-24)
CTL/CTLParser/EvaluateableProposition.h (+13/-0)
CTL/PetriNets/OnTheFlyDG.cpp (+15/-2)
PetriEngine/SuccessorGenerator.cpp (+3/-1)
PetriParse/QueryXMLParser.cpp (+2/-2)
To merge this branch: bzr merge lp:~tapaal-dist-ctl/verifypn/arithmeticExpressions
Reviewer Review Type Date Requested Status
Jiri Srba Needs Fixing
Review via email: mp+325912@code.launchpad.net

This proposal has been superseded by a proposal from 2017-06-22.

Description of the change

Added the requested syntax for arithmetic expressions:
 integer-sum
 integer-product
 integer-difference

To post a comment you must log in.
Revision history for this message
Jiri Srba (srba) wrote :

I can see some problems when parsing the expressions.

A query in the GUI is:

EF N.P0 * N.P1 + N.P2 * N.P2 - N.P4 = 0

and your engine prints it as:

Query before reduction: AG (((P0 + P1) * ((P2 + P2) - P4)) == 0)

but the XML query output seems correct:

 <exists-path>
        <finally>
          <integer-eq>
            <integer-sum>
              <integer-product>
                <tokens-count>
                  <place>P0</place>
                </tokens-count>
                <tokens-count>
                  <place>P1</place>
                </tokens-count>
              </integer-product>
              <integer-difference>
                <integer-product>
                  <tokens-count>
                    <place>P2</place>
                  </tokens-count>
                  <tokens-count>
                    <place>P2</place>
                  </tokens-count>
                </integer-product>
                <tokens-count>
                  <place>P4</place>
                </tokens-count>
              </integer-difference>
            </integer-sum>
            <integer-constant>0</integer-constant>
          </integer-eq>
        </finally>
      </exists-path>

review: Needs Fixing
187. By Jiri Srba

fixed inhibitor arcs behaviour when removing preset in successor generator

188. By Lasse S. Jensen

integer-sum and integer-product are now correctly parsed in verifypn

Revision history for this message
Lasse S. Jensen (lasjen12) wrote :

> I can see some problems when parsing the expressions.
>
> A query in the GUI is:
>
> EF N.P0 * N.P1 + N.P2 * N.P2 - N.P4 = 0
>
> and your engine prints it as:
>
> Query before reduction: AG (((P0 + P1) * ((P2 + P2) - P4)) == 0)
>
> but the XML query output seems correct:
>
> <exists-path>
> <finally>
> <integer-eq>
> <integer-sum>
> <integer-product>
> <tokens-count>
> <place>P0</place>
> </tokens-count>
> <tokens-count>
> <place>P1</place>
> </tokens-count>
> </integer-product>
> <integer-difference>
> <integer-product>
> <tokens-count>
> <place>P2</place>
> </tokens-count>
> <tokens-count>
> <place>P2</place>
> </tokens-count>
> </integer-product>
> <tokens-count>
> <place>P4</place>
> </tokens-count>
> </integer-difference>
> </integer-sum>
> <integer-constant>0</integer-constant>
> </integer-eq>
> </finally>
> </exists-path>

The xml query is not correct. sum and product have been swapped with each other. This was an issue in the parser in verifypn.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CTL/CTLParser/CTLParser.cpp'
--- CTL/CTLParser/CTLParser.cpp 2017-03-15 20:19:30 +0000
+++ CTL/CTLParser/CTLParser.cpp 2017-06-22 19:09:16 +0000
@@ -344,28 +344,43 @@
344 if (firstLetter == 'a') {344 if (firstLetter == 'a') {
345 //Construct all-paths345 //Construct all-paths
346 query = new CTLQuery(A, getPathOperator(root), false, "");346 query = new CTLQuery(A, getPathOperator(root), false, "");
347 assert(query->GetQuantifier() == A && "Failed setting quantifier");347 if(query->GetQuantifier() != A){
348 std::cerr << "Error: Failed setting all operator." << std::endl;
349 exit(EXIT_FAILURE);
350 }
348 }351 }
349 else if (firstLetter == 'e' ) {352 else if (firstLetter == 'e' ) {
350 //Construct exists-path353 //Construct exists-path
351 query = new CTLQuery(E, getPathOperator(root), false, "");354 query = new CTLQuery(E, getPathOperator(root), false, "");
352 assert(query->GetQuantifier() == E && "Failed setting path operator");355 if(query->GetQuantifier() != E){
356 std::cerr << "Error: Failed setting exists operator." << std::endl;
357 exit(EXIT_FAILURE);
358 }
353 }359 }
354 else if (firstLetter == 'n' ) {360 else if (firstLetter == 'n' ) {
355 //Construct negation361 //Construct negation
356 query = new CTLQuery(NEG, pError, false, "");362 query = new CTLQuery(NEG, pError, false, "");
357 assert(query->GetQuantifier() == NEG && "Failed setting negation operator");363 if(query->GetQuantifier() != NEG){
364 std::cerr << "Error: Failed setting negation operator." << std::endl;
365 exit(EXIT_FAILURE);
366 }
358 }367 }
359 else if (firstLetter == 'c' ) {368 else if (firstLetter == 'c' ) {
360 //Construct conjunction369 //Construct conjunction
361 query = new CTLQuery(AND, pError, false, "");370 query = new CTLQuery(AND, pError, false, "");
362 assert(query->GetQuantifier() == AND && "Failed setting and operator");371 if(query->GetQuantifier() != AND){
372 std::cerr << "Error: Failed setting and operator." << std::endl;
373 exit(EXIT_FAILURE);
374 }
363 }375 }
364 else if (firstLetter == 'd' ) {376 else if (firstLetter == 'd' ) {
365 if( root_name[1] == 'i' ){377 if( root_name[1] == 'i' ){
366 //Construct disjunction378 //Construct disjunction
367 query = new CTLQuery(OR, pError, false, "");379 query = new CTLQuery(OR, pError, false, "");
368 assert(query->GetQuantifier() == OR && "Failed setting or operator");380 if(query->GetQuantifier() != OR){
381 std::cerr << "Error: Failed setting or operator." << std::endl;
382 exit(EXIT_FAILURE);
383 }
369 }384 }
370 else if (root_name[1] == 'e'){385 else if (root_name[1] == 'e'){
371 //Deadlock query386 //Deadlock query
@@ -403,7 +418,7 @@
403 418
404 loperator = loperator_sym(loperator);419 loperator = loperator_sym(loperator);
405 420
406 atom_str = first + loperator + second;421 atom_str = first + "}" + loperator + "{" + second;
407 422
408 }423 }
409 else {424 else {
@@ -512,9 +527,18 @@
512 parameter_str = parameter_str + ")";527 parameter_str = parameter_str + ")";
513 }528 }
514 529
515 else if(parameter->name()[0] == 'i'){530 else if(parameter->name()[0] == 'i' && parameter->name()[8] == 'c'){
516 parameter_str = parameter_str + choppy(parameter->value()) + ")";531 parameter_str = parameter_str + choppy(parameter->value()) + ")";
517 }532 }
533 else if(parameter->name()[0] == 'i' && parameter->name()[8] == 's'){
534 parameter_str = parameter_str + parsePar(parameter->first_node()) + " + " + parsePar(parameter->first_node()->next_sibling()) + ")";
535 }
536 else if(parameter->name()[0] == 'i' && parameter->name()[8] == 'p'){
537 parameter_str = parameter_str + parsePar(parameter->first_node()) + " * " + parsePar(parameter->first_node()->next_sibling()) + ")";
538 }
539 else if(parameter->name()[0] == 'i' && parameter->name()[8] == 'd'){
540 parameter_str = parameter_str + parsePar(parameter->first_node()) + " - " + parsePar(parameter->first_node()->next_sibling()) + ")";
541 }
518 else {542 else {
519 std::cerr << "Error: Failed parsing query file provided. Incorrect format around the parameter: " << parameter->name() << ". Please check spelling." << std::endl;543 std::cerr << "Error: Failed parsing query file provided. Incorrect format around the parameter: " << parameter->name() << ". Please check spelling." << std::endl;
520 exit(EXIT_FAILURE);544 exit(EXIT_FAILURE);
521545
=== modified file 'CTL/CTLParser/CTLQuery.cpp'
--- CTL/CTLParser/CTLQuery.cpp 2017-03-12 18:46:15 +0000
+++ CTL/CTLParser/CTLQuery.cpp 2017-06-22 19:09:16 +0000
@@ -134,7 +134,7 @@
134134
135std::string CTLQuery::ToString(){135std::string CTLQuery::ToString(){
136 if(_hasAtom){136 if(_hasAtom){
137 return _a;137 return _proposition->ToString();
138 }138 }
139 else if(_q == AND){139 else if(_q == AND){
140 return "(" + _firstchild->ToString() + " & " + _secondchild->ToString() + ")";140 return "(" + _firstchild->ToString() + " & " + _secondchild->ToString() + ")";
@@ -152,13 +152,13 @@
152 }152 }
153 else quanti = "E";153 else quanti = "E";
154 if(_path == F){154 if(_path == F){
155 return quanti + "F" + _firstchild->ToString();155 return quanti + "F " + _firstchild->ToString();
156 }156 }
157 else if(_path == G){157 else if(_path == G){
158 return quanti + "G" + _firstchild->ToString();158 return quanti + "G " + _firstchild->ToString();
159 }159 }
160 else if(_path == X){160 else if(_path == X){
161 return quanti + "X" + _firstchild->ToString();161 return quanti + "X " + _firstchild->ToString();
162 }162 }
163 else if(_path == U){163 else if(_path == U){
164 return quanti + "(" + _firstchild->ToString() + ") U (" + _secondchild->ToString() + ")";164 return quanti + "(" + _firstchild->ToString() + ") U (" + _secondchild->ToString() + ")";
165165
=== modified file 'CTL/CTLParser/EvaluateableProposition.cpp'
--- CTL/CTLParser/EvaluateableProposition.cpp 2017-04-11 10:21:33 +0000
+++ CTL/CTLParser/EvaluateableProposition.cpp 2017-06-22 19:09:16 +0000
@@ -37,14 +37,14 @@
37 _loperator = SetLoperator(a);37 _loperator = SetLoperator(a);
38 assert(_loperator != NOT_CARDINALITY);38 assert(_loperator != NOT_CARDINALITY);
3939
40 size_t begin = a.find('(') + 1;40 //size_t begin = a.find('(') + 1;
41 size_t end = a.find(')') - begin;41 size_t end = a.find('}');
42 std::string first_parameter_str = a.substr(begin, end);42 std::string first_parameter_str = a.substr(0, end);
43 a = a.substr(a.find(')') + 1);43 a = a.substr(a.find('}') + 1);
4444
45 begin = a.find('(') + 1;45 size_t begin = a.find('{') + 1;
46 end = a.find(')') - begin;46 //end = a.find(')') - begin;
47 std::string second_parameter_str = a.substr(begin, end);47 std::string second_parameter_str = a.substr(begin);
48 _firstParameter = CreateParameter(first_parameter_str, net->placeNames(), net->numberOfPlaces());48 _firstParameter = CreateParameter(first_parameter_str, net->placeNames(), net->numberOfPlaces());
49 _secondParameter = CreateParameter(second_parameter_str, net->placeNames(), net->numberOfPlaces());49 _secondParameter = CreateParameter(second_parameter_str, net->placeNames(), net->numberOfPlaces());
50 }50 }
@@ -90,7 +90,8 @@
90 SetFireset("all", net->transitionNames(), net->numberOfTransitions());90 SetFireset("all", net->transitionNames(), net->numberOfTransitions());
91 }91 }
92 else{92 else{
93 assert(false && "Atomic string proposed for proposition could not be parsed");93 std::cerr << "Error: Could not identify Evaluateable Proposition type from atom string: "<<a<<"." << std::endl;
94 exit(EXIT_FAILURE);
94 }95 }
95}96}
9697
@@ -139,7 +140,51 @@
139}140}
140141
141CardinalityParameter* EvaluateableProposition::CreateParameter(std::string parameter_str, std::vector<std::string> p_names, unsigned int numberof_p){142CardinalityParameter* EvaluateableProposition::CreateParameter(std::string parameter_str, std::vector<std::string> p_names, unsigned int numberof_p){
142 CardinalityParameter *param = new CardinalityParameter(); 143 CardinalityParameter *param = new CardinalityParameter();
144 while(parameter_str.substr(0,1).compare(" ")==0){
145 parameter_str = parameter_str.substr(1);
146 }
147 //std::cout<<"ParamString: "<<parameter_str<<"\n"<<std::flush;
148
149 ParameterHolder* typeHolder = new ParameterHolder();
150 if(parameter_str.substr(0,11).compare("integer-sum")==0){
151 typeHolder->type = SUM;
152 typeHolder->body = parameter_str.substr(11);
153 }
154 else if(parameter_str.substr(0,15).compare("integer-product")==0){
155 typeHolder->type = PRODUCT;
156 typeHolder->body = parameter_str.substr(15);
157 }
158 else if(parameter_str.substr(0,18).compare("integer-difference")==0){
159 typeHolder->type = DIFF;
160 typeHolder->body = parameter_str.substr(18);
161 }
162 else if(parameter_str.substr(0,16).compare("integer-constant")==0){
163 typeHolder->type = CONST;
164 typeHolder->body = parameter_str.substr(16);
165 }
166 else if(parameter_str.substr(0,12).compare("tokens-count")==0){
167 typeHolder->type = PLACE;
168 typeHolder->body = parameter_str.substr(12);
169 }
170 else{
171 std::cerr << "Error: Internal parse error - \"" << parameter_str <<"\" has unrecognized beginning." << std::endl;
172 exit(EXIT_FAILURE);
173 }
174
175 std::size_t found = typeHolder->body.find_last_of(")");
176 parameter_str = typeHolder->body.substr(1,found-1);
177
178 if(typeHolder->type != CONST && typeHolder->type != PLACE){
179 std::size_t end_of_first = GetEndingParamIndex(parameter_str) + 1;
180 param->isArithmetic = true;
181 param->arithmetictype = typeHolder->type;
182 param->arithmA = CreateParameter(parameter_str.substr(0,end_of_first), p_names, numberof_p);
183 param->arithmB = CreateParameter(parameter_str.substr(end_of_first + 2), p_names, numberof_p);
184 return param;
185 }
186
187
143 char c;188 char c;
144 if(sscanf(parameter_str.c_str(), "%d%c", &param->value, &c) == 1) {189 if(sscanf(parameter_str.c_str(), "%d%c", &param->value, &c) == 1) {
145 //If string is identifier starting with a number, you will read two items.190 //If string is identifier starting with a number, you will read two items.
@@ -178,8 +223,30 @@
178 return param;223 return param;
179}224}
180225
226std::size_t EvaluateableProposition::GetEndingParamIndex(std::string param_str){
227 size_t pos = param_str.find('(');
228 size_t start_count =1;
229 size_t end_count =0;
230 std::string temp = param_str.substr(pos+1);
231 while(start_count != end_count){
232 size_t new_pos = 0;
233 if(temp.find('(') < temp.find(')')){
234 start_count++;
235 new_pos = temp.find('(') + 1;
236 }
237 else{
238 end_count++;
239 new_pos = temp.find(')') + 1;
240 }
241 pos = pos + new_pos;
242 temp = temp.substr(new_pos);
243 }
244
245 return pos;
246}
247
181LoperatorType EvaluateableProposition::SetLoperator(std::string atom_str){248LoperatorType EvaluateableProposition::SetLoperator(std::string atom_str){
182 std::string loperator_str = atom_str.substr(atom_str.find(')') + 1);249 std::string loperator_str = atom_str.substr(atom_str.find('}') + 1);
183 loperator_str = loperator_str.substr(0, 4);250 loperator_str = loperator_str.substr(0, 4);
184 if(loperator_str.compare(" le ")== 0)251 if(loperator_str.compare(" le ")== 0)
185 return LEQ;252 return LEQ;
@@ -206,22 +273,60 @@
206 return fire_str + ")";273 return fire_str + ")";
207 }274 }
208 else if (_type == CARDINALITY){275 else if (_type == CARDINALITY){
209 std::string cardi_str = "(";276 return Parameter_tostring(_firstParameter) + Loperator_tostring() + Parameter_tostring(_secondParameter);
210 if(_firstParameter->isPlace)277 }
211 cardi_str = cardi_str + "place(" + patch::to_string(_firstParameter->value) + ")";278 std::cerr << "Error: An unknown error occured while converting a proposition to string. " << std::endl;
212 else279 exit(EXIT_FAILURE);
213 cardi_str = cardi_str = patch::to_string(_firstParameter->value);280}
214 281
215 cardi_str = cardi_str + " loperator ";282
216 283std::string EvaluateableProposition::Parameter_tostring(CardinalityParameter* param){
217 if(_secondParameter->isPlace)284 std::string cardi_str = "";
218 cardi_str = cardi_str + "place(" + patch::to_string(_secondParameter->value) + ")";285 if(param->isPlace){
219 else286 cardi_str = cardi_str + "place(";
220 cardi_str = cardi_str = patch::to_string(_secondParameter->value);287 int i = 0;
221 return cardi_str + ")";288 while(i != param->places_i.size()){
289 cardi_str = cardi_str + patch::to_string(param->places_i[i]);
290
291 if(++i < param->places_i.size()){
292 cardi_str = cardi_str + ", ";
293 }
294 }
295 cardi_str = cardi_str + ")";
296 }
297 else if(param->isArithmetic){
298 std::string arthm_ope = "";
299 if(param->arithmetictype == SUM)
300 arthm_ope = " + ";
301 else if (param->arithmetictype == PRODUCT)
302 arthm_ope = " * ";
303 else if (param->arithmetictype == DIFF)
304 arthm_ope = " - ";
305 else {
306 std::cerr << "Error: An unknown error occured while converting a proposition to string. " << std::endl;
307 exit(EXIT_FAILURE);
308 }
309 cardi_str = cardi_str + Parameter_tostring(param->arithmA) + arthm_ope + Parameter_tostring(param->arithmB);
222 }310 }
223 else311 else
224 std::cerr << "Error: An unknown error occured while converting a proposition to string. " << std::endl;312 cardi_str = cardi_str = patch::to_string(param->value);
313 return cardi_str;
314}
315
316std::string EvaluateableProposition::Loperator_tostring(){
317 if(_loperator == LEQ)
318 return " <= ";
319 else if (_loperator == GRQ)
320 return " >= ";
321 else if (_loperator == EQ)
322 return " == ";
323 else if (_loperator == GR)
324 return " > ";
325 else if (_loperator == LE)
326 return " < ";
327 else if (_loperator == NE)
328 return " != ";
329 else std::cerr << "Error: Could not convert loperator to string" << std::endl;
225 exit(EXIT_FAILURE);330 exit(EXIT_FAILURE);
226}331}
227332
228333
=== modified file 'CTL/CTLParser/EvaluateableProposition.h'
--- CTL/CTLParser/EvaluateableProposition.h 2017-02-08 19:14:47 +0000
+++ CTL/CTLParser/EvaluateableProposition.h 2017-06-22 19:09:16 +0000
@@ -18,12 +18,22 @@
1818
1919
20enum PropositionType {PropError = -1, CARDINALITY = 0, FIREABILITY = 1, DEADLOCK = 2};20enum PropositionType {PropError = -1, CARDINALITY = 0, FIREABILITY = 1, DEADLOCK = 2};
21enum ArithmeticType {NON = -1, SUM = 0, PRODUCT = 1, DIFF = 2, CONST = 3, PLACE = 4};
21enum LoperatorType {LopError = -1, NOT_CARDINALITY = -1, EQ = 0, LE = 1, LEQ = 2, GR = 3, GRQ = 4, NE = 5};22enum LoperatorType {LopError = -1, NOT_CARDINALITY = -1, EQ = 0, LE = 1, LEQ = 2, GR = 3, GRQ = 4, NE = 5};
2223
24struct ParameterHolder{
25 ArithmeticType type = NON;
26 std::string body = "";
27};
28
23struct CardinalityParameter{29struct CardinalityParameter{
24 bool isPlace = false;30 bool isPlace = false;
31 bool isArithmetic = false;
25 int value = -1;32 int value = -1;
26 std::vector<int> places_i;33 std::vector<int> places_i;
34 ArithmeticType arithmetictype = NON;
35 CardinalityParameter* arithmA;
36 CardinalityParameter* arithmB;
27};37};
2838
29class EvaluateableProposition {39class EvaluateableProposition {
@@ -39,6 +49,7 @@
39private:49private:
40 void SetFireset(std::string fireset_str, std::vector<std::string> t_names, unsigned int numberof_t);50 void SetFireset(std::string fireset_str, std::vector<std::string> t_names, unsigned int numberof_t);
41 CardinalityParameter* CreateParameter(std::string parameter_str, std::vector<std::string> p_names, unsigned int numberof_p);51 CardinalityParameter* CreateParameter(std::string parameter_str, std::vector<std::string> p_names, unsigned int numberof_p);
52 std::size_t GetEndingParamIndex(std::string parameter_str);
42 LoperatorType SetLoperator(std::string atom_str);53 LoperatorType SetLoperator(std::string atom_str);
43 54
44 PropositionType _type = PropError;55 PropositionType _type = PropError;
@@ -46,6 +57,8 @@
46 std::vector<int> _fireset;57 std::vector<int> _fireset;
47 CardinalityParameter* _firstParameter = nullptr;58 CardinalityParameter* _firstParameter = nullptr;
48 CardinalityParameter* _secondParameter = nullptr;59 CardinalityParameter* _secondParameter = nullptr;
60 std::string Parameter_tostring(CardinalityParameter *param);
61 std::string Loperator_tostring();
49 62
50};63};
5164
5265
=== modified file 'CTL/PetriNets/OnTheFlyDG.cpp'
--- CTL/PetriNets/OnTheFlyDG.cpp 2017-04-11 19:03:34 +0000
+++ CTL/PetriNets/OnTheFlyDG.cpp 2017-06-22 19:09:16 +0000
@@ -395,9 +395,22 @@
395 }395 }
396 return res;396 return res;
397 }397 }
398 else{398 else if(param->isArithmetic){
399 return param->value;399 if(param->arithmetictype == NON){
400 std::cerr << "Error: Arithmetic param is not assigned a type"<< std::endl;
401 exit(EXIT_FAILURE);
402 }
403 else if(param->arithmetictype == SUM){
404 return GetParamValue(param->arithmA, marking) + GetParamValue(param->arithmB, marking);
405 }
406 else if(param->arithmetictype == PRODUCT){
407 return GetParamValue(param->arithmA, marking) * GetParamValue(param->arithmB, marking);
408 }
409 else if(param->arithmetictype == DIFF){
410 return GetParamValue(param->arithmA, marking) - GetParamValue(param->arithmB, marking);
411 }
400 }412 }
413 return param->value;
401}414}
402415
403bool OnTheFlyDG::EvalCardianlity(int a, LoperatorType lop, int b) {416bool OnTheFlyDG::EvalCardianlity(int a, LoperatorType lop, int b) {
404417
=== modified file 'PetriEngine/SuccessorGenerator.cpp'
--- PetriEngine/SuccessorGenerator.cpp 2017-03-05 16:08:26 +0000
+++ PetriEngine/SuccessorGenerator.cpp 2017-06-22 19:09:16 +0000
@@ -39,7 +39,9 @@
39 uint32_t finv = ptr.inputs;39 uint32_t finv = ptr.inputs;
40 uint32_t linv = ptr.outputs;40 uint32_t linv = ptr.outputs;
41 for (; finv < linv; ++finv) {41 for (; finv < linv; ++finv) {
42 write.marking()[_net._invariants[finv].place] -= _net._invariants[finv].tokens;42 if(!_net._invariants[finv].inhibitor) {
43 write.marking()[_net._invariants[finv].place] -= _net._invariants[finv].tokens;
44 }
43 }45 }
44 }46 }
4547
4648
=== modified file 'PetriParse/QueryXMLParser.cpp'
--- PetriParse/QueryXMLParser.cpp 2017-04-09 15:12:50 +0000
+++ PetriParse/QueryXMLParser.cpp 2017-06-22 19:09:16 +0000
@@ -386,8 +386,8 @@
386 Expr_ptr child = parseIntegerExpression(it);386 Expr_ptr child = parseIntegerExpression(it);
387 if(child == NULL) return NULL;387 if(child == NULL) return NULL;
388 expr = isMult ? 388 expr = isMult ?
389 (Expr_ptr)std::make_shared<PlusExpr>(expr, child) :389 (Expr_ptr)std::make_shared<MultiplyExpr>(expr, child):
390 (Expr_ptr)std::make_shared<MultiplyExpr>(expr, child);390 (Expr_ptr)std::make_shared<PlusExpr>(expr, child);
391 }391 }
392 return expr;392 return expr;
393 } else if (elementName == "integer-difference") {393 } else if (elementName == "integer-difference") {

Subscribers

People subscribed via source and target branches