expression.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. 
  2. #ifndef DSR_BUILDER_EXPRESSION_MODULE
  3. #define DSR_BUILDER_EXPRESSION_MODULE
  4. #include "../../../DFPSR/api/stringAPI.h"
  5. // The expression module is a slow but generic system for evaluating expressions where all data is stored as strings for simplicity.
  6. // No decimal numbers allowed, because it requires both human readable syntax and full determinism without precision loss.
  7. enum Notation {
  8. Prefix = 0,
  9. Infix = 1,
  10. Postfix = 2
  11. };
  12. enum Associativity {
  13. LeftToRight = 0,
  14. RightToLeft = 1
  15. };
  16. struct Operation {
  17. int16_t symbolIndex;
  18. std::function<dsr::String(dsr::ReadableString, dsr::ReadableString)> action;
  19. Operation(int16_t symbolIndex, std::function<dsr::String(dsr::ReadableString, dsr::ReadableString)> action);
  20. };
  21. struct Precedence {
  22. Notation notation;
  23. Associativity associativity;
  24. dsr::List<Operation> operations;
  25. Precedence(Notation notation, Associativity associativity);
  26. };
  27. struct POIndex {
  28. int16_t precedenceIndex = -1;
  29. int16_t operationIndex = -1;
  30. POIndex();
  31. POIndex(int16_t precedenceIndex, int16_t operationIndex);
  32. };
  33. enum class SymbolType {
  34. Nothing, // Whitespace does not produce any tokens, but counts as atomic.
  35. Atomic, // Will separate even directly connected to other tokens. These should not contain regular characters, to prevent cutting up identifiers.
  36. Keyword // The remains between atomic symbols and whilespace. Two keywords in a row needs to be separated by something else.
  37. };
  38. struct Symbol {
  39. dsr::String token;
  40. SymbolType symbolType;
  41. POIndex operations[3]; // prefix, infix and postfix
  42. int32_t depthOffset;
  43. dsr::DsrChar endsWith = -1; // If endsWith is not -1, the token will consume everything until the endsWith character not preceded by escapes is found.
  44. dsr::DsrChar escapes = -1;
  45. Symbol(const dsr::ReadableString &token, SymbolType symbolType, int32_t depthOffset, dsr::DsrChar endsWith, dsr::DsrChar escapes);
  46. };
  47. struct ExpressionSyntax {
  48. dsr::List<Symbol> symbols;
  49. dsr::List<Precedence> precedences;
  50. int16_t atomicCount = 0;
  51. int16_t keywordCount = 0;
  52. ExpressionSyntax();
  53. };
  54. dsr::String expression_unwrapIfNeeded(const dsr::ReadableString &text);
  55. dsr::ReadableString expression_getToken(const dsr::List<dsr::String> &tokens, int64_t index, const dsr::ReadableString &outside);
  56. int64_t expression_interpretAsInteger(const dsr::ReadableString &value);
  57. dsr::String expression_evaluate(const dsr::List<dsr::String> &tokens, std::function<dsr::String(dsr::ReadableString)> identifierEvaluation);
  58. dsr::String expression_evaluate(const dsr::List<dsr::String> &tokens, int64_t startTokenIndex, int64_t endTokenIndex, std::function<dsr::String(dsr::ReadableString)> identifierEvaluation);
  59. dsr::String expression_evaluate(const dsr::List<dsr::String> &tokens, int64_t startTokenIndex, int64_t endTokenIndex, const ExpressionSyntax &syntax, std::function<dsr::String(dsr::ReadableString)> identifierEvaluation);
  60. // Tokenizing into pure lists of strings is inefficient redundant work,
  61. // but a lot more reusable than a list of custom types hard-coded for a specific parser.
  62. void expression_tokenize(dsr::List<dsr::String> &targetTokens, const dsr::ReadableString &sourceText, const ExpressionSyntax &syntax);
  63. void expression_tokenize(dsr::List<dsr::String> &targetTokens, const dsr::ReadableString &sourceText);
  64. dsr::List<dsr::String> expression_tokenize(const dsr::ReadableString &sourceText, const ExpressionSyntax &syntax);
  65. dsr::List<dsr::String> expression_tokenize(const dsr::ReadableString &sourceText);
  66. void expression_runRegressionTests();
  67. #endif