libqasm
library for handling cQASM files
cqasm-version.cpp
Go to the documentation of this file.
1 
5 #include "cqasm-version.hpp"
6 #include "cqasm-error.hpp"
9 
10 namespace cqasm {
11 namespace version {
12 
16 Version::Version(const std::string &version) {
17  if (version.empty()) {
18  return;
19  }
20  size_t next, last = 0;
21  while ((next = version.find('.', last)) != std::string::npos) {
22  push_back(std::stoi(version.substr(last, next - last)));
23  last = next + 1;
24  }
25  push_back(std::stoi(version.substr(last)));
26  for (auto component : *this) {
27  if (component < 0) {
28  throw std::invalid_argument("version component below zero");
29  }
30  }
31 }
32 
40 int Version::compare(const Version &other) const {
41  for (size_t i = 0; i < this->size() || i < other.size(); i++) {
42  auto lhs = i < this->size() ? (*this)[i] : 0;
43  auto rhs = i < other.size() ? other[i] : 0;
44  if (lhs > rhs) return 1;
45  if (lhs < rhs) return -1;
46  }
47  return 0;
48 }
49 
57 int Version::compare(const std::string &other) const {
58  return compare(Version(other));
59 }
60 
64 std::ostream &operator<<(std::ostream &os, const Version &object) {
65  bool first = true;
66  for (auto item : object) {
67  if (first) {
68  first = false;
69  } else {
70  os << ".";
71  }
72  os << item;
73  }
74  return os;
75 }
76 
81 Version parse_file(const std::string &filename) {
82  return std::move(ParseHelper(filename, "", true).version);
83 }
84 
90 Version parse_file(FILE *file, const std::string &filename) {
91  auto retval = std::move(ParseHelper(filename, file).version);
92  if (fseek(file, 0, SEEK_SET)) {
93  throw error::AnalysisError("failed to rewind file pointer");
94  }
95  return retval;
96 }
97 
103 Version parse_string(const std::string &data, const std::string &filename) {
104  return std::move(ParseHelper(filename, data, false).version);
105 }
106 
113 ParseHelper::ParseHelper(
114  const std::string &filename,
115  const std::string &data,
116  bool use_file
117 ) : filename(filename), version("") {
118 
119  // Create the scanner.
120  if (!construct()) return;
121 
122  // Open the file or pass the data buffer to flex.
123  if (use_file) {
124  fptr = fopen(filename.c_str(), "r");
125  if (!fptr) {
126  std::ostringstream sb;
127  sb << "Failed to open input file " << filename << ": "
128  << strerror(errno);
129  push_error(sb.str());
130  return;
131  }
132  cqasm_versionset_in(fptr, (yyscan_t)scanner);
133  } else {
134  buf = cqasm_version_scan_string(data.c_str(), (yyscan_t)scanner);
135  }
136 
137  // Do the actual parsing.
138  parse();
139 
140 }
141 
146 ParseHelper::ParseHelper(
147  const std::string &filename,
148  FILE *fptr
149 ) : filename(filename), version("") {
150 
151  // Create the scanner.
152  if (!construct()) return;
153 
154  // Open the file or pass the data buffer to flex.
155  cqasm_versionset_in(fptr, (yyscan_t)scanner);
156 
157  // Do the actual parsing.
158  parse();
159 
160 }
161 
165 bool ParseHelper::construct() {
166  int retcode = cqasm_versionlex_init((yyscan_t*)&scanner);
167  if (retcode) {
168  std::ostringstream sb;
169  sb << "Failed to construct scanner: " << strerror(retcode);
170  push_error(sb.str());
171  return false;
172  } else {
173  return true;
174  }
175 }
176 
180 void ParseHelper::parse() {
181  int retcode = cqasm_versionparse((yyscan_t) scanner, *this);
182  if (retcode == 2) {
183  std::ostringstream sb;
184  sb << "Out of memory while parsing " << filename;
185  push_error(sb.str());
186  return;
187  } else if (retcode) {
188  std::ostringstream sb;
189  sb << "Failed to parse " << filename;
190  push_error(sb.str());
191  return;
192  }
193  if (version.empty()) {
194  throw error::AnalysisError(
195  "Internal error; no version info nor error info was returned "
196  "by version parser");
197  }
198 }
199 
204  if (fptr) {
205  fclose(fptr);
206  }
207  if (buf) {
209  }
210  if (scanner) {
212  }
213 }
214 
218 void ParseHelper::push_error(const std::string &error) {
219  throw error::AnalysisError(std::string(error));
220 }
221 
222 } // namespace version
223 } // namespace cqasm
Defines utilities for detecting and dealing with cQASM language versions.
Version parse_file(const std::string &filename)
Parse the given file to get its version number.
Toplevel namespace with entry points for the new API.
void cqasm_version_delete_buffer(YY_BUFFER_STATE b, yyscan_t yyscanner)
Destroy the buffer.
void cqasm_versionset_in(FILE *_in_str, yyscan_t yyscanner)
Set the input stream.
YY_BUFFER_STATE cqasm_version_scan_string(yyconst char *yy_str, yyscan_t yyscanner)
Setup the input buffer state to scan a string.
int cqasm_versionparse(yyscan_t scanner, cqasm::version::ParseHelper &helper)
Version(const std::string &version="1.0")
Constructs a version object from a string, defaulting to 1.0.
Version number primitive used within the AST and semantic trees.
void * yyscan_t
std::ostream & operator<<(std::ostream &os, const Version &object)
Stream << overload for version nodes.
Internal helper class for parsing cQASM file versions.
int cqasm_versionlex_destroy(yyscan_t yyscanner)
Contains custom exception objects used by libqasm.
int cqasm_versionlex_init(yyscan_t *scanner)
static void push_error(const std::string &error)
Pushes an error.
virtual ~ParseHelper()
Destroys the parse helper.
Version parse_string(const std::string &data, const std::string &filename)
Parse the given string as a file to get its version number.
int compare(const Version &other) const
Compares this version against the other version.
Parser, generated by Bison.
Exception used for analysis errors.
Definition: cqasm-error.hpp:27