operators.hpp
Go to the documentation of this file.
1 /* Copyright (C) 2022 Davide Faconti - All Rights Reserved
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
4 * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
5 * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
10 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 #pragma once
14 
15 #include <cmath>
16 #include <memory>
17 #include <string>
18 #include <vector>
19 
22 
23 // Naive implementation of an AST with simple evaluation function.
24 namespace BT::Ast
25 {
27 
28 using expr_ptr = std::shared_ptr<struct ExprBase>;
29 
30 // extended strin to number that consider enums and booleans
31 inline double StringToDouble(const Any& value, const Environment& env)
32 {
33  const auto str = value.cast<std::string>();
34  if(str == "true")
35  {
36  return 1.0;
37  }
38  if(str == "false")
39  {
40  return 0.0;
41  }
42  if(env.enums)
43  {
44  auto it = env.enums->find(str);
45  if(it != env.enums->end())
46  {
47  return it->second;
48  }
49  }
50  return value.cast<double>();
51 }
52 
53 struct ExprBase
54 {
55  using Ptr = std::shared_ptr<ExprBase>;
56 
57  virtual ~ExprBase() = default;
58  virtual Any evaluate(Environment& env) const = 0;
59 };
60 
61 inline std::string ErrorNotInit(const char* side, const char* op_str)
62 {
63  return StrCat("The ", side, " operand of the operator [", op_str,
64  "] is not initialized");
65 }
66 
68 {
70 
72  {}
73 
74  Any evaluate(Environment&) const override
75  {
76  return value;
77  }
78 };
79 
81 {
82  std::string name;
83 
84  explicit ExprName(std::string n) : name(LEXY_MOV(n))
85  {}
86 
87  Any evaluate(Environment& env) const override
88  {
89  //search first in the enums table
90  if(env.enums)
91  {
92  auto enum_ptr = env.enums->find(name);
93  if(enum_ptr != env.enums->end())
94  {
95  return Any(double(enum_ptr->second));
96  }
97  }
98  // search now in the variables table
99  auto any_ref = env.vars->getAnyLocked(name);
100  if(!any_ref)
101  {
102  throw RuntimeError(StrCat("Variable not found: ", name));
103  }
104  return *any_ref.get();
105  }
106 };
107 
109 {
110  enum op_t
111  {
115  } op;
117 
119  {}
120 
121  Any evaluate(Environment& env) const override
122  {
123  auto rhs_v = rhs->evaluate(env);
124  if(rhs_v.isNumber())
125  {
126  const double rv = rhs_v.cast<double>();
127  switch(op)
128  {
129  case negate:
130  return Any(-rv);
131  case complement:
132  return Any(static_cast<double>(~static_cast<int64_t>(rv)));
133  case logical_not:
134  return Any(static_cast<double>(!static_cast<bool>(rv)));
135  }
136  }
137  else if(rhs_v.isString())
138  {
139  throw RuntimeError("Invalid operator for std::string");
140  }
141  throw RuntimeError("ExprUnaryArithmetic: undefined");
142  }
143 };
144 
146 {
147  enum op_t
148  {
154 
158 
161  } op;
162 
163  const char* opStr() const
164  {
165  switch(op)
166  {
167  case plus:
168  return "+";
169  case minus:
170  return "-";
171  case times:
172  return "*";
173  case div:
174  return "/";
175  case concat:
176  return "..";
177  case bit_and:
178  return "&";
179  case bit_or:
180  return "|";
181  case bit_xor:
182  return "^";
183  case logic_and:
184  return "&&";
185  case logic_or:
186  return "||";
187  }
188  return "";
189  }
190 
192 
194  : op(op), lhs(LEXY_MOV(lhs)), rhs(LEXY_MOV(rhs))
195  {}
196 
197  Any evaluate(Environment& env) const override
198  {
199  auto lhs_v = lhs->evaluate(env);
200  auto rhs_v = rhs->evaluate(env);
201 
202  if(lhs_v.empty())
203  {
204  throw RuntimeError(ErrorNotInit("left", opStr()));
205  }
206  if(rhs_v.empty())
207  {
208  throw RuntimeError(ErrorNotInit("right", opStr()));
209  }
210 
211  if(rhs_v.isNumber() && lhs_v.isNumber())
212  {
213  auto lv = lhs_v.cast<double>();
214  auto rv = rhs_v.cast<double>();
215 
216  switch(op)
217  {
218  case plus:
219  return Any(lv + rv);
220  case minus:
221  return Any(lv - rv);
222  case times:
223  return Any(lv * rv);
224  case div:
225  return Any(lv / rv);
226  default: {
227  }
228  }
229 
230  if(op == bit_and || op == bit_or || op == bit_xor)
231  {
232  try
233  {
234  int64_t li = lhs_v.cast<int64_t>();
235  int64_t ri = rhs_v.cast<int64_t>();
236  switch(op)
237  {
238  case bit_and:
239  return Any(static_cast<double>(li & ri));
240  case bit_or:
241  return Any(static_cast<double>(li | ri));
242  case bit_xor:
243  return Any(static_cast<double>(li ^ ri));
244  default: {
245  }
246  }
247  }
248  catch(...)
249  {
250  throw RuntimeError("Binary operators are not allowed if "
251  "one of the operands is not an integer");
252  }
253  }
254 
255  if(op == logic_or || op == logic_and)
256  {
257  try
258  {
259  auto lb = lhs_v.cast<bool>();
260  auto rb = rhs_v.cast<bool>();
261  switch(op)
262  {
263  case logic_or:
264  return Any(static_cast<double>(lb || rb));
265  case logic_and:
266  return Any(static_cast<double>(lb && rb));
267  default: {
268  }
269  }
270  }
271  catch(...)
272  {
273  throw RuntimeError("Logic operators are not allowed if "
274  "one of the operands is not castable to bool");
275  }
276  }
277  }
278  else if(rhs_v.isString() && lhs_v.isString() && op == plus)
279  {
280  return Any(lhs_v.cast<std::string>() + rhs_v.cast<std::string>());
281  }
282  else if(op == concat && ((rhs_v.isString() && lhs_v.isString()) ||
283  (rhs_v.isString() && lhs_v.isNumber()) ||
284  (rhs_v.isNumber() && lhs_v.isString())))
285  {
286  return Any(lhs_v.cast<std::string>() + rhs_v.cast<std::string>());
287  }
288  else
289  {
290  throw RuntimeError("Operation not permitted");
291  }
292 
293  return {}; // unreachable
294  }
295 };
296 
297 template <typename T>
298 bool IsSame(const T& lv, const T& rv)
299 {
300  if constexpr(std::is_same_v<double, T>)
301  {
302  constexpr double EPS = static_cast<double>(std::numeric_limits<float>::epsilon());
303  return std::abs(lv - rv) <= EPS;
304  }
305  else
306  {
307  return (lv == rv);
308  }
309 }
310 
312 {
313  enum op_t
314  {
321  };
322 
323  const char* opStr(op_t op) const
324  {
325  switch(op)
326  {
327  case equal:
328  return "==";
329  case not_equal:
330  return "!=";
331  case less:
332  return "<";
333  case greater:
334  return ">";
335  case less_equal:
336  return "<=";
337  case greater_equal:
338  return ">=";
339  }
340  return "";
341  }
342 
343  std::vector<op_t> ops;
344  std::vector<expr_ptr> operands;
345 
346  Any evaluate(Environment& env) const override
347  {
348  auto SwitchImpl = [&](const auto& lv, const auto& rv, op_t op) {
349  switch(op)
350  {
351  case equal:
352  if(!IsSame(lv, rv))
353  return false;
354  break;
355  case not_equal:
356  if(IsSame(lv, rv))
357  return false;
358  break;
359  case less:
360  if(lv >= rv)
361  return false;
362  break;
363  case greater:
364  if(lv <= rv)
365  return false;
366  break;
367  case less_equal:
368  if(lv > rv)
369  return false;
370  break;
371  case greater_equal:
372  if(lv < rv)
373  return false;
374  break;
375  }
376  return true;
377  };
378 
379  auto lhs_v = operands[0]->evaluate(env);
380  for(auto i = 0u; i != ops.size(); ++i)
381  {
382  auto rhs_v = operands[i + 1]->evaluate(env);
383 
384  if(lhs_v.empty())
385  {
386  throw RuntimeError(ErrorNotInit("left", opStr(ops[i])));
387  }
388  if(rhs_v.empty())
389  {
390  throw RuntimeError(ErrorNotInit("right", opStr(ops[i])));
391  }
392  const Any False(0.0);
393 
394  if(lhs_v.isNumber() && rhs_v.isNumber())
395  {
396  auto lv = lhs_v.cast<double>();
397  auto rv = rhs_v.cast<double>();
398  if(!SwitchImpl(lv, rv, ops[i]))
399  {
400  return False;
401  }
402  }
403  else if(lhs_v.isString() && rhs_v.isString())
404  {
405  auto lv = lhs_v.cast<SimpleString>();
406  auto rv = rhs_v.cast<SimpleString>();
407  if(!SwitchImpl(lv, rv, ops[i]))
408  {
409  return False;
410  }
411  }
412  else if(lhs_v.isString() && rhs_v.isNumber())
413  {
414  auto lv = StringToDouble(lhs_v, env);
415  auto rv = rhs_v.cast<double>();
416  if(!SwitchImpl(lv, rv, ops[i]))
417  {
418  return False;
419  }
420  }
421  else if(lhs_v.isNumber() && rhs_v.isString())
422  {
423  auto lv = lhs_v.cast<double>();
424  auto rv = StringToDouble(rhs_v, env);
425  if(!SwitchImpl(lv, rv, ops[i]))
426  {
427  return False;
428  }
429  }
430  else
431  {
432  throw RuntimeError(StrCat("Can't mix different types in Comparison. "
433  "Left operand [",
434  BT::demangle(lhs_v.type()), "] right operand [",
435  BT::demangle(rhs_v.type()), "]"));
436  }
437  lhs_v = rhs_v;
438  }
439  return Any(1.0);
440  }
441 };
442 
443 struct ExprIf : ExprBase
444 {
446 
449  {}
450 
451  Any evaluate(Environment& env) const override
452  {
453  const auto& v = condition->evaluate(env);
454  bool valid = (v.isType<SimpleString>() && v.cast<SimpleString>().size() > 0) ||
455  (v.cast<double>() != 0.0);
456  if(valid)
457  {
458  return then->evaluate(env);
459  }
460  else
461  {
462  return else_->evaluate(env);
463  }
464  }
465 };
466 
468 {
469  enum op_t
470  {
477  } op;
478 
479  const char* opStr() const
480  {
481  switch(op)
482  {
483  case assign_create:
484  return ":=";
485  case assign_existing:
486  return "=";
487  case assign_plus:
488  return "+=";
489  case assign_minus:
490  return "-=";
491  case assign_times:
492  return "*=";
493  case assign_div:
494  return "/=";
495  }
496  return "";
497  }
498 
500 
501  explicit ExprAssignment(expr_ptr _lhs, op_t op, expr_ptr _rhs)
502  : op(op), lhs(LEXY_MOV(_lhs)), rhs(LEXY_MOV(_rhs))
503  {}
504 
505  Any evaluate(Environment& env) const override
506  {
507  auto varname = dynamic_cast<ExprName*>(lhs.get());
508  if(!varname)
509  {
510  throw RuntimeError("Assignment left operand not a blackboard entry");
511  }
512  const auto& key = varname->name;
513 
514  auto entry = env.vars->getEntry(key);
515  if(!entry)
516  {
517  // variable doesn't exist, create it if using operator assign_create
518  if(op == assign_create)
519  {
520  env.vars->createEntry(key, PortInfo());
521  entry = env.vars->getEntry(key);
522  if(!entry)
523  {
524  throw LogicError("Bug: report");
525  }
526  }
527  else
528  {
529  // fail otherwise
530  auto msg = StrCat("The blackboard entry [", key,
531  "] doesn't exist, yet.\n"
532  "If you want to create a new one, "
533  "use the operator "
534  "[:=] instead of [=]");
535  throw RuntimeError(msg);
536  }
537  }
538  auto value = rhs->evaluate(env);
539 
540  std::scoped_lock lock(entry->entry_mutex);
541  auto* dst_ptr = &entry->value;
542 
543  auto errorPrefix = [dst_ptr, &key]() {
544  return StrCat("Error assigning a value to entry [", key, "] with type [",
545  BT::demangle(dst_ptr->type()), "]. ");
546  };
547 
548  if(value.empty())
549  {
550  throw RuntimeError(ErrorNotInit("right", opStr()));
551  }
552 
553  if(op == assign_create || op == assign_existing)
554  {
555  // the very fist assignment can come from any type.
556  // In the future, type check will be done by Any::copyInto
557  if(dst_ptr->empty() && entry->info.type() == typeid(AnyTypeAllowed))
558  {
559  *dst_ptr = value;
560  }
561  else if(value.isString() && !dst_ptr->isString())
562  {
563  // special case: string to other type.
564  // Check if we can use the StringConverter
565  auto const str = value.cast<std::string>();
566  const auto* entry_info = env.vars->entryInfo(key);
567 
568  if(auto converter = entry_info->converter())
569  {
570  *dst_ptr = converter(str);
571  }
572  else if(dst_ptr->isNumber())
573  {
574  auto num_value = StringToDouble(value, env);
575  *dst_ptr = Any(num_value);
576  }
577  else
578  {
579  auto msg = StrCat(errorPrefix(),
580  "\nThe right operand is a string, "
581  "can't convert to ",
582  demangle(dst_ptr->type()));
583  throw RuntimeError(msg);
584  }
585  }
586  else
587  {
588  try
589  {
590  value.copyInto(*dst_ptr);
591  }
592  catch(std::exception&)
593  {
594  auto msg = StrCat(errorPrefix(), "\nThe right operand has type [",
595  BT::demangle(value.type()), "] and can't be converted to [",
596  BT::demangle(dst_ptr->type()), "]");
597  throw RuntimeError(msg);
598  }
599  }
600  entry->sequence_id++;
601  entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
602  return *dst_ptr;
603  }
604 
605  if(dst_ptr->empty())
606  {
607  throw RuntimeError(ErrorNotInit("left", opStr()));
608  }
609 
610  // temporary use
611  Any temp_variable = *dst_ptr;
612 
613  if(value.isNumber())
614  {
615  if(!temp_variable.isNumber())
616  {
617  throw RuntimeError("This Assignment operator can't be used "
618  "with a non-numeric type");
619  }
620 
621  auto lv = temp_variable.cast<double>();
622  auto rv = value.cast<double>();
623  switch(op)
624  {
625  case assign_plus:
626  temp_variable = Any(lv + rv);
627  break;
628  case assign_minus:
629  temp_variable = Any(lv - rv);
630  break;
631  case assign_times:
632  temp_variable = Any(lv * rv);
633  break;
634  case assign_div:
635  temp_variable = Any(lv / rv);
636  break;
637  default: {
638  }
639  }
640  }
641  else if(value.isString())
642  {
643  if(op == assign_plus)
644  {
645  auto lv = temp_variable.cast<std::string>();
646  auto rv = value.cast<std::string>();
647  temp_variable = Any(lv + rv);
648  }
649  else
650  {
651  throw RuntimeError("Operator not supported for strings");
652  }
653  }
654 
655  temp_variable.copyInto(*dst_ptr);
656  entry->sequence_id++;
657  entry->stamp = std::chrono::steady_clock::now().time_since_epoch();
658  return *dst_ptr;
659  }
660 };
661 } // namespace BT::Ast
662 
663 namespace BT::Grammar
664 {
665 namespace dsl = lexy::dsl;
666 
667 constexpr auto escaped_newline = dsl::backslash >> dsl::newline;
668 
669 // An expression that is nested inside another expression.
671 {
672  // We change the whitespace rule to allow newlines:
673  // as it's nested, the REPL can properly handle continuation lines.
674  static constexpr auto whitespace = dsl::ascii::space | escaped_newline;
675  // The rule itself just recurses back to expression, but with the adjusted whitespace now.
676  static constexpr auto rule = dsl::recurse<struct Expression>;
677 
678  static constexpr auto value = lexy::forward<Ast::expr_ptr>;
679 };
680 
681 // An arbitrary expression.
682 // It uses lexy's built-in support for operator precedence parsing to automatically generate a
683 // proper rule. This is done by inheriting from expression_production.
685 {
687  {
688  static constexpr auto name = "expected operand";
689  };
690 
691  // We need to specify the atomic part of an expression.
692  static constexpr auto atom = [] {
693  auto paren_expr = dsl::parenthesized(dsl::p<nested_expr>);
694  auto boolean = dsl::p<BooleanLiteral>;
695  auto var = dsl::p<Name>;
696  auto literal = dsl::p<AnyValue>;
697 
698  return paren_expr | boolean | var | literal | dsl::error<expected_operand>;
699  }();
700 
701  // Each of the nested classes defines one operation.
702  // They inherit from a tag type that specify the kind of operation (prefix, infix, postfix),
703  // and associativity (left, right, single (non-associative)),
704  // and specify the operator rule and operand.
705 
706  // -x
707  struct math_prefix : dsl::prefix_op
708  {
709  static constexpr auto op = dsl::op<Ast::ExprUnaryArithmetic::negate>(LEXY_LIT("-"));
710  using operand = dsl::atom;
711  };
712  // x * x, x / x
713  struct math_product : dsl::infix_op_left
714  {
715  static constexpr auto op = [] {
716  // Don't confuse with *= or /=
717  auto times = dsl::not_followed_by(LEXY_LIT("*"), dsl::lit_c<'='>);
718  auto div = dsl::not_followed_by(LEXY_LIT("/"), dsl::lit_c<'='>);
719  return dsl::op<Ast::ExprBinaryArithmetic::times>(times) /
720  dsl::op<Ast::ExprBinaryArithmetic::div>(div);
721  }();
723  };
724  // x + x, x - x
725  struct math_sum : dsl::infix_op_left
726  {
727  static constexpr auto op = [] {
728  // Don't confuse with += or -=
729  auto plus = dsl::not_followed_by(LEXY_LIT("+"), dsl::lit_c<'='>);
730  auto minus = dsl::not_followed_by(LEXY_LIT("-"), dsl::lit_c<'='>);
731  return dsl::op<Ast::ExprBinaryArithmetic::plus>(plus) /
732  dsl::op<Ast::ExprBinaryArithmetic::minus>(minus);
733  }();
734 
736  };
737 
738  // x .. y
739  struct string_concat : dsl::infix_op_left
740  {
741  static constexpr auto op = [] {
742  return dsl::op<Ast::ExprBinaryArithmetic::concat>(LEXY_LIT(".."));
743  }();
744 
745  using operand = math_sum;
746  };
747 
748  // ~x
749  struct bit_prefix : dsl::prefix_op
750  {
751  static constexpr auto op = [] {
752  auto complement = LEXY_LIT("~");
753  auto logical_not = dsl::not_followed_by(LEXY_LIT("!"), dsl::lit_c<'='>);
754 
755  return dsl::op<Ast::ExprUnaryArithmetic::complement>(complement) /
756  dsl::op<Ast::ExprUnaryArithmetic::logical_not>(logical_not);
757  }();
758  using operand = dsl::atom;
759  };
760 
761  // x & x
762  struct bit_and : dsl::infix_op_left
763  {
764  static constexpr auto op = [] {
765  // Don't confuse with &&
766  auto bit_and = dsl::not_followed_by(LEXY_LIT("&"), dsl::lit_c<'&'>);
767  return dsl::op<Ast::ExprBinaryArithmetic::bit_and>(bit_and);
768  }();
769 
771  };
772 
773  // x | x, x ^ x
774  struct bit_or : dsl::infix_op_left
775  {
776  static constexpr auto op = [] {
777  // Don't confuse with ||
778  auto bit_or = dsl::not_followed_by(LEXY_LIT("|"), dsl::lit_c<'|'>);
779  return dsl::op<Ast::ExprBinaryArithmetic::bit_or>(bit_or) /
780  dsl::op<Ast::ExprBinaryArithmetic::bit_xor>(LEXY_LIT("^"));
781  }();
782 
783  using operand = bit_and;
784  };
785 
786  // Comparisons are list operators, which allows implementation of chaining.
787  // x == y < z
788  struct comparison : dsl::infix_op_list
789  {
790  // Other comparison operators omitted for simplicity.
791  static constexpr auto op = dsl::op<Ast::ExprComparison::equal>(LEXY_LIT("==")) /
792  dsl::op<Ast::ExprComparison::not_equal>(LEXY_LIT("!=")) /
793  dsl::op<Ast::ExprComparison::less>(LEXY_LIT("<")) /
794  dsl::op<Ast::ExprComparison::greater>(LEXY_LIT(">")) /
795  dsl::op<Ast::ExprComparison::less_equal>(LEXY_LIT("<=")) /
796  dsl::op<Ast::ExprComparison::greater_equal>(LEXY_LIT(">"
797  "="));
798 
799  // The use of dsl::groups ensures that an expression can either contain math or bit
800  // operators. Mixing requires parenthesis.
801  using operand = dsl::groups<math_sum, bit_or>;
802  };
803 
804  // Logical operators, || and &&
805  struct logical : dsl::infix_op_left
806  {
807  static constexpr auto op =
808  dsl::op<Ast::ExprBinaryArithmetic::logic_or>(LEXY_LIT("||")) /
809  dsl::op<Ast::ExprBinaryArithmetic::logic_and>(LEXY_LIT("&&"));
810 
811  using operand = dsl::groups<string_concat, comparison>;
812  };
813 
814  // x ? y : z
815  struct conditional : dsl::infix_op_single
816  {
817  // We treat a conditional operator, which has three operands,
818  // as a binary operator where the operator consists of ?, the inner operator, and :.
819  // The <void> ensures that `dsl::op` does not produce a value.
820  static constexpr auto op =
821  dsl::op<void>(LEXY_LIT("?") >> (dsl::p<nested_expr> + dsl::lit_c<':'>));
822  using operand = logical;
823  };
824 
825  struct assignment : dsl::infix_op_single
826  {
827  // We need to prevent `=` from matching `==`.
828  static constexpr auto op =
829  dsl::op<Ast::ExprAssignment::assign_create>(LEXY_LIT(":=")) /
830  dsl::op<Ast::ExprAssignment::assign_existing>(
831  dsl::not_followed_by(LEXY_LIT("="), dsl::lit_c<'='>)) /
832  dsl::op<Ast::ExprAssignment::assign_plus>(LEXY_LIT("+=")) /
833  dsl::op<Ast::ExprAssignment::assign_minus>(LEXY_LIT("-=")) /
834  dsl::op<Ast::ExprAssignment::assign_times>(LEXY_LIT("*=")) /
835  dsl::op<Ast::ExprAssignment::assign_div>(LEXY_LIT("/="));
836 
838  };
839 
840  // An expression also needs to specify the operation with the lowest binding power.
841  // The operation of everything else is determined by following the `::operand` member.
843 
844  static constexpr auto value =
845  // We need a sink as the comparison expression generates a list.
846  lexy::fold_inplace<std::unique_ptr<Ast::ExprComparison>>(
847  [] { return std::make_unique<Ast::ExprComparison>(); },
848  [](auto& node, Ast::expr_ptr opr) { node->operands.push_back(LEXY_MOV(opr)); },
849  [](auto& node, Ast::ExprComparison::op_t op) { node->ops.push_back(op); })
850  // The result of the list feeds into a callback that handles all other cases.
851  >> lexy::callback(
852  // atoms
853  lexy::forward<Ast::expr_ptr>, lexy::new_<Ast::ExprLiteral, Ast::expr_ptr>,
854  lexy::new_<Ast::ExprName, Ast::expr_ptr>,
855  // unary/binary operators
856  lexy::new_<Ast::ExprUnaryArithmetic, Ast::expr_ptr>,
857  lexy::new_<Ast::ExprBinaryArithmetic, Ast::expr_ptr>,
858  // conditional and assignment
859  lexy::new_<Ast::ExprIf, Ast::expr_ptr>,
860  lexy::new_<Ast::ExprAssignment, Ast::expr_ptr>);
861 };
862 
863 // A statement, which is a list of expressions separated by semicolons.
864 struct stmt
865 {
866  // We don't allow newlines as whitespace at the top-level.
867  // This is because we can't easily know whether we need to request more input when seeing a
868  // newline or not. Once we're having a e.g. parenthesized expression, we know that we need more
869  // input until we've reached ), so then change the whitespace rule.
871 
872  static constexpr auto rule = [] {
873  // We can't use `dsl::eol` as our terminator directly,
874  // since that would try and skip whitespace, which requests more input on the REPL.
875  auto at_eol = dsl::peek(dsl::eol);
876  return dsl::terminator(at_eol).opt_list(dsl::p<Expression>, dsl::sep(dsl::semicolon));
877  }();
878 
879  static constexpr auto value = lexy::as_list<std::vector<Ast::expr_ptr>>;
880 };
881 
882 } // namespace BT::Grammar
BT::Grammar::Expression
Definition: operators.hpp:684
BT::Grammar::Expression::assignment
Definition: operators.hpp:825
BT::PortInfo
Definition: basic_types.h:392
BT::Ast::ExprBinaryArithmetic::lhs
expr_ptr lhs
Definition: operators.hpp:191
BT::Ast::ExprAssignment::assign_div
@ assign_div
Definition: operators.hpp:476
LEXY_MOV
#define LEXY_MOV(...)
Definition: config.hpp:21
BT::Ast::ExprComparison::greater
@ greater
Definition: operators.hpp:318
BT::demangle
std::string demangle(char const *name)
Definition: demangle_util.h:74
BT::Ast::ExprAssignment::assign_times
@ assign_times
Definition: operators.hpp:475
BT::Ast::ExprComparison::not_equal
@ not_equal
Definition: operators.hpp:316
BT::Grammar::Expression::logical::operand
dsl::groups< string_concat, comparison > operand
Definition: operators.hpp:811
lexyd::peek
constexpr auto peek(Rule)
Definition: peek.hpp:166
BT::Ast::ExprAssignment::lhs
expr_ptr lhs
Definition: operators.hpp:499
BT::Ast::ExprBinaryArithmetic::div
@ div
Definition: operators.hpp:152
BT::Ast::ExprAssignment
Definition: operators.hpp:467
BT::Ast::ExprLiteral::ExprLiteral
ExprLiteral(Any v)
Definition: operators.hpp:71
BT::Any
Definition: safe_any.hpp:36
BT::Ast::ExprUnaryArithmetic::ExprUnaryArithmetic
ExprUnaryArithmetic(op_t op, expr_ptr e)
Definition: operators.hpp:118
LEXY_LIT
#define LEXY_LIT(Str)
Definition: literal.hpp:390
BT::Ast::ExprIf
Definition: operators.hpp:443
BT::Grammar::Expression::assignment::op
static constexpr auto op
Definition: operators.hpp:828
lexyd::sep
constexpr auto sep(Branch)
Defines a separator for a list.
Definition: separator.hpp:91
BT::Grammar::Expression::string_concat::op
static constexpr auto op
Definition: operators.hpp:741
BT::Ast::Environment::enums
EnumsTablePtr enums
Definition: script_parser.hpp:34
BT::Ast::ExprUnaryArithmetic::complement
@ complement
Definition: operators.hpp:113
lexyd::terminator
constexpr auto terminator(Branch)
Creates a terminator using the given branch.
Definition: terminator.hpp:106
SafeAny::SimpleString::size
std::size_t size() const
Definition: simple_string.hpp:88
BT::Ast::ExprBinaryArithmetic::logic_or
@ logic_or
Definition: operators.hpp:160
BT::Ast::ExprName
Definition: operators.hpp:80
BT::Grammar::Expression::bit_or::op
static constexpr auto op
Definition: operators.hpp:776
BT::Ast::ExprBase::evaluate
virtual Any evaluate(Environment &env) const =0
BT::Ast::ExprUnaryArithmetic::op_t
op_t
Definition: operators.hpp:110
BT::Ast::ExprComparison::opStr
const char * opStr(op_t op) const
Definition: operators.hpp:323
BT::Ast::ExprComparison::op_t
op_t
Definition: operators.hpp:313
BT::Ast::ExprName::evaluate
Any evaluate(Environment &env) const override
Definition: operators.hpp:87
BT::Grammar::Expression::string_concat
Definition: operators.hpp:739
BT::Ast::ExprBinaryArithmetic::logic_and
@ logic_and
Definition: operators.hpp:159
BT::Ast::ExprIf::evaluate
Any evaluate(Environment &env) const override
Definition: operators.hpp:451
BT::Ast::ExprBinaryArithmetic::bit_xor
@ bit_xor
Definition: operators.hpp:157
BT::Ast::ExprAssignment::assign_minus
@ assign_minus
Definition: operators.hpp:474
BT::Grammar::Expression::math_sum
Definition: operators.hpp:725
BT::Ast::ExprUnaryArithmetic::negate
@ negate
Definition: operators.hpp:112
BT::Ast::Environment::vars
BT::Blackboard::Ptr vars
Definition: script_parser.hpp:33
BT::Grammar::Expression::math_prefix::op
static constexpr auto op
Definition: operators.hpp:709
BT::Grammar::Expression::value
static constexpr auto value
Definition: operators.hpp:844
BT::Ast::ExprIf::then
expr_ptr then
Definition: operators.hpp:445
lexyd::parenthesized
constexpr auto parenthesized
Definition: brackets.hpp:112
BT::Grammar::Expression::comparison
Definition: operators.hpp:788
lexyd::ascii::newline
constexpr auto newline
Definition: ascii.hpp:77
BT::Ast::ExprLiteral::value
Any value
Definition: operators.hpp:69
BT::Grammar::Expression::conditional::op
static constexpr auto op
Definition: operators.hpp:820
BT::Grammar::Expression::comparison::op
static constexpr auto op
Definition: operators.hpp:791
BT::Ast::ExprComparison::greater_equal
@ greater_equal
Definition: operators.hpp:320
BT::Ast::ExprUnaryArithmetic::rhs
expr_ptr rhs
Definition: operators.hpp:116
BT::Ast::ExprBinaryArithmetic::ExprBinaryArithmetic
ExprBinaryArithmetic(expr_ptr lhs, op_t op, expr_ptr rhs)
Definition: operators.hpp:193
BT::Grammar::Expression::bit_and::op
static constexpr auto op
Definition: operators.hpp:764
BT::Grammar::Expression::atom
static constexpr auto atom
Definition: operators.hpp:692
BT::Any::isNumber
bool isNumber() const
Definition: safe_any.hpp:311
BT::Grammar::Expression::expected_operand::name
static constexpr auto name
Definition: operators.hpp:688
BT::Ast::ExprBinaryArithmetic::evaluate
Any evaluate(Environment &env) const override
Definition: operators.hpp:197
BT::Ast::ExprName::name
std::string name
Definition: operators.hpp:82
lexy::_detail::any_ref
any_base * any_ref
Definition: any_ref.hpp:43
BT::LogicError
Definition: exceptions.h:45
BT::Ast::ExprIf::ExprIf
ExprIf(expr_ptr condition, expr_ptr then, expr_ptr else_)
Definition: operators.hpp:447
BT::Ast::ExprComparison::operands
std::vector< expr_ptr > operands
Definition: operators.hpp:344
any_types.hpp
BT::Ast::ExprBinaryArithmetic::opStr
const char * opStr() const
Definition: operators.hpp:163
BT::Grammar::Expression::math_prefix
Definition: operators.hpp:707
lexyd::eol
constexpr auto eol
Matches the end of line (EOF or newline).
Definition: newline.hpp:79
BT::Ast::ExprComparison::ops
std::vector< op_t > ops
Definition: operators.hpp:343
BT::Grammar::Expression::math_product::op
static constexpr auto op
Definition: operators.hpp:715
BT::Ast::ExprBinaryArithmetic::bit_and
@ bit_and
Definition: operators.hpp:155
BT::Grammar::nested_expr
Definition: operators.hpp:670
BT::Grammar::stmt::whitespace
static constexpr auto whitespace
Definition: operators.hpp:870
BT::Ast::SimpleString
SafeAny::SimpleString SimpleString
Definition: operators.hpp:26
lexy::callback
constexpr auto callback(Fns &&... fns)
Creates a callback.
Definition: adapter.hpp:21
BT::Grammar::stmt::rule
static constexpr auto rule
Definition: operators.hpp:872
BT::Grammar::Expression::bit_prefix
Definition: operators.hpp:749
BT::Ast::ExprAssignment::op
enum BT::Ast::ExprAssignment::op_t op
BT::Ast::ExprBinaryArithmetic::op
enum BT::Ast::ExprBinaryArithmetic::op_t op
BT::Ast::expr_ptr
std::shared_ptr< struct ExprBase > expr_ptr
Definition: operators.hpp:28
BT::Ast::ExprComparison::less
@ less
Definition: operators.hpp:317
BT::Grammar::stmt::value
static constexpr auto value
Definition: operators.hpp:879
BT::Grammar::Expression::logical
Definition: operators.hpp:805
lexyd::not_followed_by
constexpr auto not_followed_by(Literal, CharClass cc)
Match a literal but only if not followed by the given char class.
Definition: follow.hpp:100
BT::Ast::ExprBinaryArithmetic::plus
@ plus
Definition: operators.hpp:149
BT::Ast::ExprBinaryArithmetic::op_t
op_t
Definition: operators.hpp:147
BT::Ast::ErrorNotInit
std::string ErrorNotInit(const char *side, const char *op_str)
Definition: operators.hpp:61
BT::Ast::ExprUnaryArithmetic::logical_not
@ logical_not
Definition: operators.hpp:114
BT::Ast::ExprLiteral::evaluate
Any evaluate(Environment &) const override
Definition: operators.hpp:74
BT::RuntimeError
Definition: exceptions.h:58
BT::Ast::ExprName::ExprName
ExprName(std::string n)
Definition: operators.hpp:84
BT::Grammar::Expression::bit_and
Definition: operators.hpp:762
SafeAny::SimpleString
Definition: simple_string.hpp:18
BT::Ast::ExprBase::~ExprBase
virtual ~ExprBase()=default
BT::Grammar::Expression::comparison::operand
dsl::groups< math_sum, bit_or > operand
Definition: operators.hpp:801
BT::Ast::ExprComparison::evaluate
Any evaluate(Environment &env) const override
Definition: operators.hpp:346
BT::Ast::ExprComparison::less_equal
@ less_equal
Definition: operators.hpp:319
BT::Any::cast
T cast() const
Definition: safe_any.hpp:146
BT::Ast::ExprBinaryArithmetic::concat
@ concat
Definition: operators.hpp:153
magic_enum::detail::n
constexpr auto n() noexcept
Definition: magic_enum.hpp:417
BT::Ast::ExprComparison
Definition: operators.hpp:311
BT::StrCat
std::string StrCat()
Definition: strcat.hpp:46
BT::Ast::ExprAssignment::rhs
expr_ptr rhs
Definition: operators.hpp:499
BT::Grammar::Expression::bit_prefix::op
static constexpr auto op
Definition: operators.hpp:751
lexy::op
typename LEXY_DECAY_DECLTYPE(Operator)::op_tag_type op
Definition: operator.hpp:41
BT::Grammar::Expression::math_sum::op
static constexpr auto op
Definition: operators.hpp:727
BT::Ast::ExprUnaryArithmetic
Definition: operators.hpp:108
BT::AnyTypeAllowed
Definition: basic_types.h:87
BT::Grammar::nested_expr::rule
static constexpr auto rule
Definition: operators.hpp:676
BT::Ast::ExprAssignment::assign_plus
@ assign_plus
Definition: operators.hpp:473
BT::Ast::ExprLiteral
Definition: operators.hpp:67
lexy::transparent_production
Definition: grammar.hpp:151
BT::Grammar::Expression::conditional
Definition: operators.hpp:815
BT::Ast::ExprAssignment::op_t
op_t
Definition: operators.hpp:469
BT::Ast::ExprAssignment::opStr
const char * opStr() const
Definition: operators.hpp:479
BT::Ast::ExprBinaryArithmetic::bit_or
@ bit_or
Definition: operators.hpp:156
BT::Grammar
Definition: any_types.hpp:22
BT::Ast::ExprBinaryArithmetic::times
@ times
Definition: operators.hpp:151
BT::Grammar::Expression::bit_or
Definition: operators.hpp:774
BT::Any::copyInto
void copyInto(Any &dst)
Definition: safe_any.hpp:322
BT::Ast::StringToDouble
double StringToDouble(const Any &value, const Environment &env)
Definition: operators.hpp:31
lexyd::ascii::space
constexpr auto space
Definition: ascii.hpp:112
BT::Grammar::Expression::bit_prefix::operand
dsl::atom operand
Definition: operators.hpp:758
BT::Grammar::Expression::logical::op
static constexpr auto op
Definition: operators.hpp:807
lexy::expression_production
Definition: expression.hpp:581
BT::Ast::ExprBinaryArithmetic::rhs
expr_ptr rhs
Definition: operators.hpp:191
BT::Grammar::escaped_newline
constexpr auto escaped_newline
Definition: operators.hpp:667
BT::Grammar::Expression::math_product
Definition: operators.hpp:713
BT::Ast::ExprIf::else_
expr_ptr else_
Definition: operators.hpp:445
BT::Ast::ExprIf::condition
expr_ptr condition
Definition: operators.hpp:445
lexyd::ascii::blank
constexpr auto blank
Definition: ascii.hpp:60
BT::Ast::ExprBinaryArithmetic
Definition: operators.hpp:145
BT::Grammar::nested_expr::value
static constexpr auto value
Definition: operators.hpp:678
lexyd::times
constexpr auto times(Rule)
Repeats the rule N times in sequence.
Definition: times.hpp:40
BT::Ast::ExprBase
Definition: operators.hpp:53
BT::Ast::ExprBinaryArithmetic::minus
@ minus
Definition: operators.hpp:150
BT::Ast::ExprAssignment::ExprAssignment
ExprAssignment(expr_ptr _lhs, op_t op, expr_ptr _rhs)
Definition: operators.hpp:501
BT::Grammar::stmt
Definition: operators.hpp:864
script_parser.hpp
lexy::_detail::any_base::get
constexpr T & get() noexcept
Definition: any_ref.hpp:25
BT::Ast::ExprUnaryArithmetic::evaluate
Any evaluate(Environment &env) const override
Definition: operators.hpp:121
BT::Ast::IsSame
bool IsSame(const T &lv, const T &rv)
Definition: operators.hpp:298
BT::Grammar::Expression::expected_operand
Definition: operators.hpp:686
BT::Ast::ExprAssignment::assign_create
@ assign_create
Definition: operators.hpp:471
BT::Grammar::Expression::math_prefix::operand
dsl::atom operand
Definition: operators.hpp:710
BT::Ast::ExprBase::Ptr
std::shared_ptr< ExprBase > Ptr
Definition: operators.hpp:55
BT::Grammar::nested_expr::whitespace
static constexpr auto whitespace
Definition: operators.hpp:674
BT::Ast::ExprAssignment::assign_existing
@ assign_existing
Definition: operators.hpp:472
BT::Ast::ExprUnaryArithmetic::op
enum BT::Ast::ExprUnaryArithmetic::op_t op
BT::Ast::ExprComparison::equal
@ equal
Definition: operators.hpp:315
BT::Ast::ExprAssignment::evaluate
Any evaluate(Environment &env) const override
Definition: operators.hpp:505
BT::Ast
Definition: operators.hpp:24
BT::Ast::Environment
The Environment class is used to encapsulate the information and states needed by the scripting langu...
Definition: script_parser.hpp:31


behaviortree_cpp_v4
Author(s): Davide Faconti
autogenerated on Fri Jun 28 2024 02:20:07