CASM  1.1.0
A Clusters Approach to Statistical Mechanics
DataFormatter.cc
Go to the documentation of this file.
1 #include <boost/algorithm/string.hpp>
2 #include <boost/lexical_cast.hpp>
3 #include <boost/tokenizer.hpp>
5 #include <iostream>
6 #include <string>
7 #include <vector>
8 
10 
11 namespace CASM {
12 //****************************************************************************************
13 
14 std::pair<std::vector<long>, std::vector<long> > index_expression_to_bounds(
15  const std::string &_expr) {
16  // std::cout << "Parsing index expression: " << _expr << "\n";
17  typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
18  boost::char_separator<char> sep1(","), sep2(" \t", ":");
19  tokenizer tok1(_expr, sep1);
20  std::vector<std::string> split_expr(tok1.begin(), tok1.end());
21  std::vector<long> ind_vec_begin(split_expr.size());
22  std::vector<long> ind_vec_end(split_expr.size());
23  for (Index i = 0; i < split_expr.size(); i++) {
24  tokenizer tok2(split_expr[i], sep2);
25  std::vector<std::string> ind_expr(tok2.begin(), tok2.end());
26  if (ind_expr.size() == 1) {
27  if (ind_expr[0][0] == ':')
28  ind_vec_begin[i] = -1;
29  else
30  ind_vec_begin[i] = boost::lexical_cast<long>(ind_expr[0]);
31  ind_vec_end[i] = ind_vec_begin[i];
32  } else if (ind_expr.size() == 3) {
33  ind_vec_begin[i] = boost::lexical_cast<long>(ind_expr[0]);
34  ind_vec_end[i] = boost::lexical_cast<long>(ind_expr[2]);
35  } else
36  throw std::runtime_error(
37  std::string(
38  "In index_expression_to_bounds(), invalid index expression \"") +
39  _expr + "\"");
40  }
41  // std::cout << "Lower bound: " << ind_vec_begin << "\n";
42  // std::cout << "upper bound: " << ind_vec_end << "\n";
43  return std::make_pair(std::move(ind_vec_begin), std::move(ind_vec_end));
44 }
45 //****************************************************************************************
46 
47 std::string::const_iterator end_of_literal(std::string::const_iterator it,
48  std::string::const_iterator end_it) {
49  for (++it; it != end_it; ++it) {
50  // if character specifies escape, consume additional character
51  if (*it == '\\')
52  ++it;
53  else if ((*it) == '\'')
54  return ++it;
55  }
56  return it;
57 }
58 
59 //****************************************************************************************
60 /*
61  * break 'input' string into a list of format tags and their (option) arguments
62  */
63 void split_formatter_expression(const std::string &input_expr,
64  std::vector<std::string> &tag_names,
65  std::vector<std::string> &sub_exprs) {
66  std::string::const_iterator it(input_expr.cbegin()),
67  it_end(input_expr.cend()), t_it1, t_it2;
68  while (it != it_end) {
69  while (it != it_end && (isspace(*it) || boost::is_any_of(",#")(*it))) ++it;
70  if (it == it_end) break;
71  // Identified a formatter tag, save starting iterator
72  t_it1 = it;
73  if ((*it) == '\'') {
74  it = end_of_literal(it, it_end);
75  t_it2 = it;
76  --t_it2;
77  if (t_it2 == t_it1 || (*t_it2) != '\'') {
78  throw std::runtime_error(
79  "Mismatched quotation marks in expression:\n \"" + input_expr +
80  "\"\n");
81  }
82  } else {
83  // find end of formatter tag
84  while (it != it_end && !(isspace(*it) || (*it) == ',') && (*it) != '(' &&
85  (*it) != ')') {
86  // if character specifies escape, consume an additional character
87  if (*it == '\\') ++it;
88  ++it;
89  }
90 
91  if (*it == ')')
92  throw std::runtime_error(
93  "Mismatched parentheses in expression:\n \"" + input_expr +
94  "\"\n");
95  }
96  // push_back formatter tag, and push_back an empty string for its optional
97  // arguments
98  tag_names.push_back(std::string(t_it1, it));
99  sub_exprs.push_back(std::string());
100 
101  // no argument, we've reached beginning of new tag, so continue
102  if (it == it_end || (*it) != '(') continue;
103 
104  // from here on, we're parsing arguments:
105  while (it != it_end && isspace(*(++it)))
106  ; // skipspace
107 
108  if (*it == ',')
109  throw std::runtime_error("Stray comma in expression:\n \"" +
110  input_expr + "\"\n");
111 
112  // start of argument
113  t_it1 = it;
114 
115  // stop at end of string, or if we hit the non-nested closing paren
116  Index paren_depth(0);
117  while (it != it_end && !((*it) == ')' && paren_depth == 0)) {
118  // if escape character, consume an additional character
119  if (*it == '\\')
120  ++it;
121  else if ((*it) == '(')
122  ++paren_depth;
123  else if ((*it) == ')')
124  --paren_depth;
125 
126  ++it;
127  }
128 
129  if (it == it_end)
130  throw std::runtime_error("Mismatched parentheses in expression:\n \"" +
131  input_expr + "\"\n");
132 
133  t_it2 = it;
134  while (isspace(*(--t_it2)))
135  ; // remove trailing space
136 
137  if (*t_it2 == ',')
138  throw std::runtime_error("Stray comma in expression:\n \"" +
139  input_expr + "\"\n");
140 
141  sub_exprs.back() = std::string(t_it1, ++t_it2);
142 
143  ++it;
144  }
145 }
146 } // namespace CASM
Main CASM namespace.
Definition: APICommand.hh:8
std::pair< std::vector< long >, std::vector< long > > index_expression_to_bounds(const std::string &_expr)
std::string::const_iterator end_of_literal(std::string::const_iterator it, std::string::const_iterator end_it)
void split_formatter_expression(const std::string &input_expr, std::vector< std::string > &tag_names, std::vector< std::string > &sub_exprs)
INDEX_TYPE Index
For long integer indexing:
Definition: definitions.hh:39