PropertyAst.hpp
Go to the documentation of this file.
1 // @formatter:off
2 //
3 // Balau core C++ library
4 //
5 // Copyright (C) 2017 Bora Software (contact@borasoftware.com)
6 //
7 // Licensed under the Boost Software License - Version 1.0 - August 17th, 2003.
8 // See the LICENSE file for the full license text.
9 //
10 
16 
17 #ifndef COM_BORA_SOFTWARE__BALAU_LANG_PROPERTY_LANG__PROPERTY_AST
18 #define COM_BORA_SOFTWARE__BALAU_LANG_PROPERTY_LANG__PROPERTY_AST
19 
24 #include <Balau/Type/Character.hpp>
25 
26 #include <memory>
27 #include <string>
28 #include <vector>
29 
31 
35 class PropertyNode { // Abstract
39  public: virtual ~PropertyNode() = default;
40 
46  public: const CodeSpan & getCodeSpan() const {
47  return codeSpan;
48  }
49 
57  public: virtual bool operator == (const PropertyNode & rhs) const {
58  return codeSpan == rhs.codeSpan;
59  }
60 
68  public: bool operator != (const PropertyNode & rhs) const {
69  return ! operator == (rhs);
70  }
71 
78  public: virtual void visit(Payload & payload, PropertyVisitor & visitor) const = 0;
79 
89  public: static std::string normalise(std::string_view input) {
90  // The output string will be at most the same length as the input string.
91  std::string output = std::string(input);
92  int inOffset = 0;
93  int outOffset = 0;
94  char32_t c;
95 
96  while (inOffset < (int) input.length()) {
97  c = Character::getNextUtf8Safe(input, inOffset);
98 
99  if (c == U'\\') {
100  if (inOffset == (int) input.length()) {
101  break; // Last character is a backslash.
102  }
103 
104  c = Character::getNextUtf8Safe(input, inOffset);
105 
106  switch (c) {
107  case U'\r':
108  case U'\n': {
109  skipLineContinuation(input, inOffset, output, outOffset);
110  break;
111  }
112 
113  default: {
114  Character::setUtf8AndAdvanceOffset(output, outOffset, c);
115  break;
116  }
117  }
118 
119  } else {
120  Character::setUtf8AndAdvanceOffset(output, outOffset, c);
121  }
122  }
123 
124  output.erase((size_t) outOffset);
125  return output;
126  }
127 
129 
130  public: PropertyNode(const PropertyNode & copy) = delete;
131  public: PropertyNode & operator = (const PropertyNode & copy) = delete;
132 
133  protected: CodeSpan codeSpan;
134 
135  protected: explicit PropertyNode(const CodeSpan & codeSpan_)
136  : codeSpan(codeSpan_) {}
137 
138  protected: PropertyNode(PropertyNode && rhs) noexcept
139  : codeSpan(rhs.codeSpan) {}
140 
141  private: static void skipLineContinuation(const std::string_view & input,
142  int & inOffset,
143  std::string & output,
144  int & outOffset) {
145  if (inOffset == (int) input.length()) {
146  return; // Last character pair is an escaped CR or LF.
147  }
148 
149  char32_t c = Character::getNextUtf8Safe(input, inOffset);
150 
151  if (c == U'\r' || c == U'\n') {
152  if (inOffset == (int) input.length()) {
153  return; // Last character triplet is an escaped CRLF or LFCR.
154  }
155 
156  c = Character::getNextUtf8Safe(input, inOffset);
157  }
158 
159  while (Character::isBlank(c)) {
160  if (inOffset == (int) input.length()) {
161  return; // End of string.
162  }
163 
164  c = Character::getNextUtf8Safe(input, inOffset);
165  }
166 
167  Character::setUtf8AndAdvanceOffset(output, outOffset, c);
168  }
169 };
170 
175 class Properties final : public PropertyNode {
181  public: Properties(const CodeSpan & codeSpan_,
182  std::string && text_,
183  std::vector<std::unique_ptr<PropertyNode>> && nodes_)
184  : PropertyNode(codeSpan_)
185  , text(std::move(text_))
186  , nodes(std::move(nodes_)) {}
187 
188  public: const std::string & getText() const {
189  return text;
190  }
191 
192  public: const std::vector<std::unique_ptr<PropertyNode>> & getNodes() const {
193  return nodes;
194  }
195 
196  public: bool operator == (const PropertyNode & rhs) const override {
197  auto * o = dynamic_cast<const Properties *>(&rhs);
198 
199  bool ret;
200  if (o == nullptr) {
201  ret = false;
202  } else {
203  ret = text == o->text
205  }
206 
207  return ret;
208  }
209 
210  public: void visit(Payload & payload, PropertyVisitor & visitor) const override {
211  visitor.visit(payload, *this);
212  }
213 
214  private: std::string text;
215  private: std::vector<std::unique_ptr<PropertyNode>> nodes;
216 };
217 
221 class ValueProperty final : public PropertyNode {
225  public: ValueProperty(const CodeSpan & codeSpan_, std::string_view name_, std::string_view value_)
226  : PropertyNode(codeSpan_)
227  , name(name_)
228  , value(value_) {}
229 
233  public: ValueProperty(ValueProperty && rhs) noexcept
234  : PropertyNode(std::move(rhs))
235  , name(rhs.name)
236  , value(rhs.value) {}
237 
243  public: std::string_view getName() const {
244  return name;
245  }
246 
252  public: std::string_view getValue() const {
253  return value;
254  }
255 
256  public: bool operator == (const PropertyNode & rhs) const override {
257  auto * o = dynamic_cast<const ValueProperty *>(&rhs);
258 
259  bool ret;
260  if (o == nullptr) {
261  ret = false;
262  } else {
263  ret = name == o->name
264  && value == o->value
266  }
267 
268  return ret;
269  }
270 
271  public: void visit(Payload & payload, PropertyVisitor & visitor) const override {
272  visitor.visit(payload, *this);
273  }
274 
276 
277  public: ValueProperty() = delete;
278  public: ValueProperty(const ValueProperty & copy) = delete;
279  public: ValueProperty & operator = (const ValueProperty & copy) = delete;
280 
281  private: std::string_view name;
282  private: std::string_view value;
283 };
284 
288 class CompositeProperty final : public PropertyNode {
292  public: CompositeProperty(const CodeSpan & codeSpan_,
293  std::string_view name_,
294  std::vector<std::unique_ptr<PropertyNode>> && nodes_)
295  : PropertyNode(codeSpan_)
296  , name(name_)
297  , nodes(std::move(nodes_)) {}
298 
302  public: CompositeProperty(CompositeProperty && rhs) noexcept
303  : PropertyNode(std::move(rhs))
304  , name(rhs.name)
305  , nodes(std::move(rhs.nodes)) {}
306 
312  public: std::string_view getName() const {
313  return name;
314  }
315 
321  public: const std::vector<std::unique_ptr<PropertyNode>> & getNodes() const {
322  return nodes;
323  }
324 
325  public: bool operator == (const PropertyNode & rhs) const override {
326  auto * o = dynamic_cast<const CompositeProperty *>(&rhs);
327 
328  bool ret;
329  if (o == nullptr) {
330  ret = false;
331  } else {
332  ret = name == o->name
333  && nodes == o->nodes
335  }
336 
337  return ret;
338  }
339 
340  public: void visit(Payload & payload, PropertyVisitor & visitor) const override {
341  visitor.visit(payload, *this);
342  }
343 
345 
346  public: CompositeProperty() = delete;
347  public: CompositeProperty(const CompositeProperty & copy) = delete;
348  public: CompositeProperty & operator = (const CompositeProperty & copy) = delete;
349 
350  private: std::string_view name;
351  private: std::vector<std::unique_ptr<PropertyNode>> nodes;
352 };
353 
357 class IncludePropertyNode final : public PropertyNode {
361  public: IncludePropertyNode(const CodeSpan & codeSpan_, std::string_view text_)
362  : PropertyNode(codeSpan_)
363  , text(text_) {}
364 
368  public: IncludePropertyNode(IncludePropertyNode && rhs) noexcept
369  : PropertyNode(std::move(rhs))
370  , text(rhs.text) {}
371 
377  public: std::string_view getText() const {
378  return text;
379  }
380 
381  public: bool operator == (const PropertyNode & rhs) const override {
382  auto * o = dynamic_cast<const IncludePropertyNode *>(&rhs);
383 
384  bool ret;
385  if (o == nullptr) {
386  ret = false;
387  } else {
388  ret = text == o->text
390  }
391 
392  return ret;
393  }
394 
395  public: void visit(Payload & payload, PropertyVisitor & visitor) const override {
396  visitor.visit(payload, *this);
397  }
398 
400 
401  public: IncludePropertyNode() = delete;
402  public: IncludePropertyNode(const IncludePropertyNode & copy) = delete;
403  public: IncludePropertyNode & operator = (const IncludePropertyNode & copy) = delete;
404 
405  private: std::string_view text;
406 };
407 
411 class CommentPropertyNode final : public PropertyNode {
415  public: CommentPropertyNode(const CodeSpan & codeSpan_, std::string_view text_)
416  : PropertyNode(codeSpan_)
417  , text(text_) {}
418 
422  public: CommentPropertyNode(CommentPropertyNode && rhs) noexcept
423  : PropertyNode(std::move(rhs))
424  , text(rhs.text) {}
425 
431  public: std::string_view getText() const {
432  return text;
433  }
434 
435  public: bool operator == (const PropertyNode & rhs) const override {
436  auto * o = dynamic_cast<const CommentPropertyNode *>(&rhs);
437 
438  bool ret;
439  if (o == nullptr) {
440  ret = false;
441  } else {
442  ret = text == o->text
444  }
445 
446  return ret;
447  }
448 
449  public: void visit(Payload & payload, PropertyVisitor & visitor) const override {
450  visitor.visit(payload, *this);
451  }
452 
454 
455  public: CommentPropertyNode() = delete;
456  public: CommentPropertyNode(const CommentPropertyNode & copy) = delete;
457  public: CommentPropertyNode & operator = (const CommentPropertyNode & copy) = delete;
458 
459  private: std::string_view text;
460 };
461 
465 class EmptyLinePropertyNode final : public PropertyNode {
469  public: explicit EmptyLinePropertyNode(const CodeSpan & codeSpan_)
470  : PropertyNode(codeSpan_) {}
471 
476  : PropertyNode(std::move(rhs)) {}
477 
478  public: bool operator == (const PropertyNode & rhs) const override {
479  auto * o = dynamic_cast<const EmptyLinePropertyNode *>(&rhs);
480 
481  bool ret;
482  if (o == nullptr) {
483  ret = false;
484  } else {
485  ret = PropertyNode::operator == (rhs);
486  }
487 
488  return ret;
489  }
490 
491  public: void visit(Payload & payload, PropertyVisitor & visitor) const override {
492  visitor.visit(payload, *this);
493  }
494 
496 
497  public: EmptyLinePropertyNode() = delete;
498  public: EmptyLinePropertyNode(const EmptyLinePropertyNode & copy) = delete;
499  public: EmptyLinePropertyNode & operator = (const EmptyLinePropertyNode & copy) = delete;
500 };
501 
502 } // namespace Balau::Lang::Property::AST
503 
504 #endif // COM_BORA_SOFTWARE__BALAU_LANG_PROPERTY_LANG__PROPERTY_AST
std::string_view getName() const
Get the string view pointing to the name of the composite property.
Definition: PropertyAst.hpp:312
void visit(Payload &payload, PropertyVisitor &visitor) const override
Visit the node.
Definition: PropertyAst.hpp:491
void visit(Payload &payload, PropertyVisitor &visitor) const override
Visit the node.
Definition: PropertyAst.hpp:210
const std::vector< std::unique_ptr< PropertyNode > > & getNodes() const
Get the string view pointing to the value of the composite property.
Definition: PropertyAst.hpp:321
virtual void visit(Payload &payload, const AST::Properties &object)=0
Visit a Properties node.
virtual void visit(Payload &payload, PropertyVisitor &visitor) const =0
Visit the node.
const CodeSpan & getCodeSpan() const
Get the code span of the node.
Definition: PropertyAst.hpp:46
Simple name-value property node.
Definition: PropertyAst.hpp:221
Information on the span of some source code text.
Definition: CodeSpan.hpp:91
STL namespace.
void visit(Payload &payload, PropertyVisitor &visitor) const override
Visit the node.
Definition: PropertyAst.hpp:449
Visitor interface for property AST nodes.
Definition: PropertyVisitor.hpp:49
EmptyLinePropertyNode(const CodeSpan &codeSpan_)
Create a blank line property node with the supplied data.
Definition: PropertyAst.hpp:469
Abstract base class of Property AST node classes.
Definition: PropertyAst.hpp:35
static bool isBlank(char32_t c)
Is the specified code point a character that visibly separates words on a line.
Definition: Character.hpp:113
std::string_view getText() const
Get the string view pointing to the text of the include property.
Definition: PropertyAst.hpp:377
CommentPropertyNode(CommentPropertyNode &&rhs) noexcept
Construct a comment property node by moving the contents of the supplied node.
Definition: PropertyAst.hpp:422
std::string_view getName() const
Get the string view pointing to the name of the value property.
Definition: PropertyAst.hpp:243
Represents a blank line in a property file.
Definition: PropertyAst.hpp:465
static char32_t getNextUtf8Safe(const std::string_view &text, int &offset)
Get the next code point from the UTF-8 string view (validating version).
Definition: Character.hpp:198
IncludePropertyNode(IncludePropertyNode &&rhs) noexcept
Construct an include property node by moving the contents of the supplied node.
Definition: PropertyAst.hpp:368
CompositeProperty(const CodeSpan &codeSpan_, std::string_view name_, std::vector< std::unique_ptr< PropertyNode >> &&nodes_)
Create a composite property node with the supplied data.
Definition: PropertyAst.hpp:292
A position in a piece of multi-line text.
virtual ~PropertyNode()=default
Destroy a Property AST node.
Composite name-value property node.
Definition: PropertyAst.hpp:288
Base class of property visitor payloads.
Definition: PropertyVisitor.hpp:39
void visit(Payload &payload, PropertyVisitor &visitor) const override
Visit the node.
Definition: PropertyAst.hpp:271
Utilities for unicode characters and code points.
ValueProperty(const CodeSpan &codeSpan_, std::string_view name_, std::string_view value_)
Create a name-value property node with the supplied data.
Definition: PropertyAst.hpp:225
Base Balau exception classes.
ValueProperty(ValueProperty &&rhs) noexcept
Construct a name-value property node by moving the contents of the supplied node. ...
Definition: PropertyAst.hpp:233
CompositeProperty(CompositeProperty &&rhs) noexcept
Construct a composite property node by moving the contents of the supplied node.
Definition: PropertyAst.hpp:302
Include property node.
Definition: PropertyAst.hpp:357
static void setUtf8AndAdvanceOffset(std::string &destination, int &offset, char32_t c)
Write a code point into the supplied UTF-8 string.
Definition: Character.hpp:329
bool operator!=(const PropertyNode &rhs) const
Returns true if the current node is not equal to the supplied node.
Definition: PropertyAst.hpp:68
Comment property node.
Definition: PropertyAst.hpp:411
std::string_view getValue() const
Get the string view pointing to the value of the value property.
Definition: PropertyAst.hpp:252
The Property parser Token enum.
void visit(Payload &payload, PropertyVisitor &visitor) const override
Visit the node.
Definition: PropertyAst.hpp:395
void visit(Payload &payload, PropertyVisitor &visitor) const override
Visit the node.
Definition: PropertyAst.hpp:340
IncludePropertyNode(const CodeSpan &codeSpan_, std::string_view text_)
Create an include property node with the supplied data.
Definition: PropertyAst.hpp:361
virtual bool operator==(const PropertyNode &rhs) const
Returns true if the current node is equal to the supplied node.
Definition: PropertyAst.hpp:57
std::string_view getText() const
Get the string view pointing to the text of the comment property.
Definition: PropertyAst.hpp:431
The Property parser abstract syntax tree node classes.
Definition: PropertyAst.hpp:30
Visitor interface for property AST nodes.
EmptyLinePropertyNode(EmptyLinePropertyNode &&rhs) noexcept
Construct a blank line property node by moving the contents of the supplied node. ...
Definition: PropertyAst.hpp:475
CommentPropertyNode(const CodeSpan &codeSpan_, std::string_view text_)
Create a comment property node with the supplied data.
Definition: PropertyAst.hpp:415
The outer structure.
Definition: PropertyAst.hpp:175
Properties(const CodeSpan &codeSpan_, std::string &&text_, std::vector< std::unique_ptr< PropertyNode >> &&nodes_)
Create a properties node.
Definition: PropertyAst.hpp:181
static std::string normalise(std::string_view input)
Removing escaping, line continuation, and leading blanks.
Definition: PropertyAst.hpp:89