btool
A parser/converter/transpiler for .bib files
Parser.cpp
Go to the documentation of this file.
1 #include <boost/filesystem/path.hpp>
2 #include <GlobalParserState.hpp>
3 #include <ParserException.hpp>
4 #include <Parser.hpp>
5 #include <algorithm>
6 #include <numeric>
7 
8 using namespace std::literals::string_literals;
9 
19  const std::optional<boost::filesystem::path> &ruleFilePath,
20  std::vector<std::string> targetStyles,
21  const bool allowAll
22 ) : targetStyles(std::move(targetStyles)),
23  translationTable(TranslationTable(ruleFilePath)),
24  allowAll{allowAll} {}
25 
34  std::optional<std::stringstream> ruleFileContents,
35  std::vector<std::string> targetStyles,
36  const bool allowAll
37 ) : targetStyles(std::move(targetStyles)),
38  translationTable(TranslationTable(std::move(ruleFileContents))),
39  allowAll{allowAll} {}
40 
50  const boost::filesystem::path &inputPath,
51  const std::optional<std::string> &sorting
52 ) const -> std::vector<BibElement> {
53  if (!boost::filesystem::exists(inputPath)) {
54  throw std::invalid_argument("No such file or directory. [path=" + inputPath.string() + "]");
55  } else if (boost::filesystem::is_directory(inputPath)) {
56  std::vector<BibElement> collector{};
57  for (const auto &file : boost::filesystem::directory_iterator(inputPath)) {
58  std::ifstream inFile{file.path().string()};
59  inFile >> std::noskipws;
60  std::string inContent{std::istream_iterator<char>{inFile}, std::istream_iterator<char>{}};
61  for (const auto &element : generate(std::string_view(inContent), sorting, inputPath.string())) {
62  collector.push_back(element);
63  }
64  }
65  if (sorting) sortElements(collector, sorting.value());
66  return collector;
67  } else if (boost::filesystem::is_regular_file(inputPath)) {
68  std::ifstream inFile{inputPath.string()};
69  inFile >> std::noskipws;
70  std::string inContent{std::istream_iterator<char>{inFile}, std::istream_iterator<char>{}};
71  auto elements = generate(std::string_view(inContent), sorting, inputPath.string());
72  if (sorting) sortElements(elements, sorting.value());
73  return elements;
74  } else {
75  throw std::invalid_argument("Unexpected file-descriptor. [path=" + inputPath.string() + "]");
76  }
77 }
78 
88  std::string_view inputFileContent,
89  const std::optional<std::string> &sorting,
90  const std::string &filename
91 ) const -> std::vector<BibElement> {
92  const std::vector<StyleProperties> targetStructures = translationTable.stylePropertiesOf(targetStyles);
93  std::vector<BibElement> parsedElements = Parser::elementsOf(inputFileContent, filename);
94  if (allowAll) {
95  if (sorting) sortElements(parsedElements, sorting.value());
96  return parsedElements;
97  } else if (targetStructures.empty()) {
98  return {};
99  } else {
100  auto filteredElements = filterElements(parsedElements, targetStructures);
101  if (sorting) sortElements(filteredElements, sorting.value());
102  return filteredElements;
103  }
104 }
105 
114  std::string_view input,
115  const std::string &filename
116 ) -> std::vector<BibElement> {
117  ParserContext context(filename);
118  std::vector<BibElement> result;
119  try {
120  delete std::accumulate<std::string_view::iterator, ParserState *>(
121  std::cbegin(input),
122  std::cend(input),
123  new GlobalParserState{context, result},
124  [&context](ParserState *const acc, const char it) -> ParserState * {
125  ++context.column;
126  if (it == '\n') {
127  ++context.line;
128  context.column = 0;
129  return acc;
130  }
131  return acc->handleCharacter(it);
132  });
133  return result;
134  } catch (ParserException &e) {
135  delete e.state;
136  throw std::runtime_error(e.what());
137  }
138 }
139 
145 auto Parser::sortElements(std::vector<BibElement> &elements, const std::string &sorting) noexcept -> void {
146  std::sort(
147  std::begin(elements),
148  std::end(elements),
149  [&sorting](const BibElement &l, const BibElement &r) {
150  return l.findAttribute(sorting).value_or<Field>({""s, ""s}).value
151  < r.findAttribute(sorting).value_or<Field>({""s, ""s}).value;
152  }
153  );
154 }
155 
165  const std::vector<boost::filesystem::path> &inputPaths,
166  const std::optional<std::string> &sorting
167 ) const -> std::vector<BibElement> {
168  std::vector<BibElement> parsedElements;
169  std::for_each(
170  std::cbegin(inputPaths),
171  std::cend(inputPaths),
172  [this, &parsedElements, &sorting](const boost::filesystem::path &p) {
173  const auto elements = generate(p, sorting);
174  parsedElements.insert(std::end(parsedElements), std::cbegin(elements), std::cend(elements));
175  }
176  );
177  if (sorting) sortElements(parsedElements, sorting.value());
178  return parsedElements;
179 }
180 
188  const std::vector<BibElement> &elements,
189  const std::vector<StyleProperties> &props
190 ) noexcept -> std::vector<BibElement> {
191  std::vector<BibElement> filteredElements{};
192  std::copy_if(
193  std::cbegin(elements),
194  std::cend(elements),
195  std::back_inserter(filteredElements),
196  [&props](const BibElement &element) {
197  return std::find_if(
198  std::cbegin(props),
199  std::cend(props),
200  [&](const StyleProperties &prop) {
201  return element.isCompliantTo(prop);
202  }
203  ) != std::cend(props);
204  }
205  );
206  return filteredElements;
207 }
GlobalParserState.hpp
ParserState
Definition: ParserState.hpp:7
StyleProperties
style-properties-container
Definition: StyleProperties.hpp:11
Parser::generate
auto generate(const std::vector< boost::filesystem::path > &inputPaths, const std::optional< std::string > &sorting) const -> std::vector< BibElement >
Definition: Parser.cpp:164
Field
Field-Container.
Definition: Field.hpp:11
BibElement::isCompliantTo
auto isCompliantTo(const StyleProperties &props) const -> bool
Definition: BibElement.cpp:12
Parser::filterElements
static auto filterElements(const std::vector< BibElement > &elements, const std::vector< StyleProperties > &props) noexcept -> std::vector< BibElement >
Definition: Parser.cpp:187
BibElement::findAttribute
auto findAttribute(const std::string &key) const noexcept -> std::optional< Field >
Definition: BibElement.cpp:46
ParserException::what
auto what() const noexcept -> const char *override
Definition: ParserException.cpp:26
ParserContext
Definition: ParserContext.hpp:10
ParserContext::column
std::size_t column
the current column the parser is parsing
Definition: ParserContext.hpp:13
ParserException.hpp
GlobalParserState
Global Parser State.
Definition: GlobalParserState.hpp:14
ParserState::handleCharacter
virtual auto handleCharacter(char c) -> ParserState *=0
Parser::Parser
Parser(const std::optional< boost::filesystem::path > &ruleFilePath, std::vector< std::string > targetStyles, const bool allowAll=false)
Definition: Parser.cpp:18
Field::value
std::string value
the value of the Field
Definition: Field.hpp:13
ParserException::state
ParserState * state
the state of the parser
Definition: ParserException.hpp:13
ParserContext::line
std::size_t line
the current line the parser is parsing
Definition: ParserContext.hpp:12
ParserException
Definition: ParserException.hpp:12
Parser::elementsOf
static auto elementsOf(std::string_view input, const std::string &filename) -> std::vector< BibElement >
Definition: Parser.cpp:113
Parser::allowAll
bool allowAll
flag that allows all styles and fields to get parsed (set when missing translationTable)
Definition: Parser.hpp:21
TranslationTable
api to interact with translation-table resource
Definition: TranslationTable.hpp:16
Parser::sortElements
static auto sortElements(std::vector< BibElement > &elements, const std::string &sorting) noexcept -> void
Definition: Parser.cpp:145
Parser.hpp
BibElement
bib-element-Container
Definition: BibElement.hpp:14