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

Proposed by Lasse S. Jensen
Status: Merged
Approved by: Jiri Srba
Approved revision: 188
Merged at revision: 183
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 Approve
Review via email: mp+326178@code.launchpad.net

This proposal supersedes a proposal from 2017-06-19.

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 : Posted in a previous version of this proposal

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
Revision history for this message
Lasse S. Jensen (lasjen12) wrote : Posted in a previous version of this proposal

> 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.

Revision history for this message
Jiri Srba (srba) :
review: Approve

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:33:43 +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:33:43 +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:33:43 +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:33:43 +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:33:43 +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:33:43 +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:33:43 +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