Minsky: 3.17.0
flowCoef.cc
Go to the documentation of this file.
1 /*
2  @copyright Steve Keen 2013
3  @author Russell Standish
4  This file is part of Minsky.
5 
6  Minsky is free software: you can redistribute it and/or modify it
7  under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  Minsky is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with Minsky. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "flowCoef.h"
21 #include "str.h"
22 #include "minsky_epilogue.h"
23 #include <ctype.h>
24 #include <stdlib.h>
25 #include <boost/spirit/include/qi.hpp>
26 namespace qi = boost::spirit::qi;
27 
28 using namespace std;
29 
30 namespace
31 {
32  // Extract leading number from a string. for ticket 1177. See https://stackoverflow.com/questions/45600212/regular-expression-multiple-floating-point.
33  bool parseLine(std::string const& line, std::string& pref) {
34  using it = std::string::const_iterator;
35 
36  // Construct grammar to treat inf and nan separately in input formula. See https://www.boost.org/doc/libs/1_68_0/libs/spirit/doc/html/spirit/qi/reference/numeric/real.html
37  qi::rule<it, std::string()> nan = -qi::lit("1.0#") >> qi::no_case["nan"] >> -('(' >> *(qi::char_ - ')') >> ')');
38  qi::rule<it, std::string()> inf = qi::no_case[qi::lit("inf") >> -qi::lit("inity")];
39  qi::rule<it, std::string()> sign = qi::lit('+') | '-';
40 
41 
42  it first = line.begin(), last = line.end();
43  return (qi::phrase_parse(first, last, -sign >> ( inf | nan) ,qi::blank, pref));
44  }
45 }
46 
47 namespace minsky
48 {
49  FlowCoef::FlowCoef(const string& formula)
50  {
51  const char* f=formula.c_str();
52  char* tail;
53  std::string prefix;
54 
55  // If NaN or inf appear in any form or case in the name of a flow coefficient, tail is set equal to f. For ticket 1177.
56  if (parseLine(formula, prefix)) {
57  tail=(char*)f;
58  } else coef=strtod(f,&tail);
59 
60  if (tail==f) // oops, that failed, check if there's a leading - sign
61  {
62  // skip whitespace
63  while (*tail != '\0' && isspace(*tail)) ++tail;
64  if (*tail=='\0')
65  {
66  coef=0;
67  return; // empty cell, nothing to do
68  }
69  if (*tail=='-')
70  {
71  coef=-1; // treat leading - sign as -1
72  tail++;
73  }
74  else
75  coef=1;
76  }
77 
78  name=trimWS(tail);
79  }
80 
81  string FlowCoef::str() const
82  {
83  if (name.empty())
84  return minsky::str(coef);
85  if (coef==1)
86  return name;
87  if (coef==-1)
88  return "-"+name;
89  return minsky::str(coef)+name;
90  }
91 
92 }
function f
Definition: canvas.m:1
STL namespace.
bool parseLine(std::string const &line, std::string &pref)
Definition: flowCoef.cc:33
std::string trimWS(const std::string &s)
Definition: str.h:49
std::string str(T x)
utility function to create a string representation of a numeric type
Definition: str.h:33