parser.hpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #pragma once
  2. namespace nall::Eval {
  3. inline auto whitespace(char n) -> bool {
  4. return n == ' ' || n == '\t' || n == '\r' || n == '\n';
  5. }
  6. inline auto parse(Node*& node, const char*& s, uint depth) -> void {
  7. auto unaryPrefix = [&](Node::Type type, uint seek, uint depth) {
  8. auto parent = new Node(type);
  9. parse(parent->link(0) = new Node, s += seek, depth);
  10. node = parent;
  11. };
  12. auto unarySuffix = [&](Node::Type type, uint seek, uint depth) {
  13. auto parent = new Node(type);
  14. parent->link(0) = node;
  15. parse(parent, s += seek, depth);
  16. node = parent;
  17. };
  18. auto binary = [&](Node::Type type, uint seek, uint depth) {
  19. auto parent = new Node(type);
  20. parent->link(0) = node;
  21. parse(parent->link(1) = new Node, s += seek, depth);
  22. node = parent;
  23. };
  24. auto ternary = [&](Node::Type type, uint seek, uint depth) {
  25. auto parent = new Node(type);
  26. parent->link(0) = node;
  27. parse(parent->link(1) = new Node, s += seek, depth);
  28. if(s[0] != ':') throw "mismatched ternary";
  29. parse(parent->link(2) = new Node, s += seek, depth);
  30. node = parent;
  31. };
  32. auto separator = [&](Node::Type type, uint seek, uint depth) {
  33. if(node->type != Node::Type::Separator) return binary(type, seek, depth);
  34. uint n = node->link.size();
  35. parse(node->link(n) = new Node, s += seek, depth);
  36. };
  37. while(whitespace(s[0])) s++;
  38. if(!s[0]) return;
  39. if(s[0] == '(' && !node->link) {
  40. parse(node, s += 1, 1);
  41. if(*s++ != ')') throw "mismatched group";
  42. }
  43. if(isLiteral(s)) {
  44. node->type = Node::Type::Literal;
  45. node->literal = literal(s);
  46. }
  47. #define p() (!node->literal && !node->link)
  48. while(true) {
  49. while(whitespace(s[0])) s++;
  50. if(!s[0]) return;
  51. if(depth >= 13) break;
  52. if(s[0] == '(' && !p()) {
  53. binary(Node::Type::Function, 1, 1);
  54. if(*s++ != ')') throw "mismatched function";
  55. continue;
  56. }
  57. if(s[0] == '[') {
  58. binary(Node::Type::Subscript, 1, 1);
  59. if(*s++ != ']') throw "mismatched subscript";
  60. continue;
  61. }
  62. if(s[0] == '.') { binary(Node::Type::Member, 1, 13); continue; }
  63. if(s[0] == '+' && s[1] == '+' && !p()) { unarySuffix(Node::Type::SuffixIncrement, 2, 13); continue; }
  64. if(s[0] == '-' && s[1] == '-' && !p()) { unarySuffix(Node::Type::SuffixDecrement, 2, 13); continue; }
  65. if(s[0] == '&' && p()) { unaryPrefix(Node::Type::Reference, 1, 12); continue; }
  66. if(s[0] == '*' && p()) { unaryPrefix(Node::Type::Dereference, 1, 12); continue; }
  67. if(s[0] == '!' && p()) { unaryPrefix(Node::Type::LogicalNot, 1, 12); continue; }
  68. if(s[0] == '~' && p()) { unaryPrefix(Node::Type::BitwiseNot, 1, 12); continue; }
  69. if(s[0] == '+' && s[1] != '+' && p()) { unaryPrefix(Node::Type::Positive, 1, 12); continue; }
  70. if(s[0] == '-' && s[1] != '-' && p()) { unaryPrefix(Node::Type::Negative, 1, 12); continue; }
  71. if(s[0] == '+' && s[1] == '+' && p()) { unaryPrefix(Node::Type::PrefixIncrement, 2, 12); continue; }
  72. if(s[0] == '-' && s[1] == '-' && p()) { unaryPrefix(Node::Type::PrefixDecrement, 2, 12); continue; }
  73. if(depth >= 12) break;
  74. if(depth >= 11) break;
  75. if(s[0] == '*' && s[1] != '=') { binary(Node::Type::Multiply, 1, 11); continue; }
  76. if(s[0] == '/' && s[1] != '=') { binary(Node::Type::Divide, 1, 11); continue; }
  77. if(s[0] == '%' && s[1] != '=') { binary(Node::Type::Modulo, 1, 11); continue; }
  78. if(depth >= 10) break;
  79. if(s[0] == '+' && s[1] != '=') { binary(Node::Type::Add, 1, 10); continue; }
  80. if(s[0] == '-' && s[1] != '=') { binary(Node::Type::Subtract, 1, 10); continue; }
  81. if(depth >= 9) break;
  82. if(s[0] == '<' && s[1] == '<' && s[2] == '<' && s[3] != '=') { binary(Node::Type::RotateLeft, 3, 9); continue; }
  83. if(s[0] == '>' && s[1] == '>' && s[2] == '>' && s[3] != '=') { binary(Node::Type::RotateRight, 3, 9); continue; }
  84. if(s[0] == '<' && s[1] == '<' && s[2] != '=') { binary(Node::Type::ShiftLeft, 2, 9); continue; }
  85. if(s[0] == '>' && s[1] == '>' && s[2] != '=') { binary(Node::Type::ShiftRight, 2, 9); continue; }
  86. if(depth >= 8) break;
  87. if(s[0] == '&' && s[1] != '&' && s[1] != '=') { binary(Node::Type::BitwiseAnd, 1, 8); continue; }
  88. if(s[0] == '|' && s[1] != '|' && s[1] != '=') { binary(Node::Type::BitwiseOr, 1, 8); continue; }
  89. if(s[0] == '^' && s[1] != '^' && s[1] != '=') { binary(Node::Type::BitwiseXor, 1, 8); continue; }
  90. if(depth >= 7) break;
  91. if(s[0] == '~' && s[1] != '=') { binary(Node::Type::Concatenate, 1, 7); continue; }
  92. if(depth >= 6) break;
  93. if(s[0] == '=' && s[1] == '=') { binary(Node::Type::Equal, 2, 6); continue; }
  94. if(s[0] == '!' && s[1] == '=') { binary(Node::Type::NotEqual, 2, 6); continue; }
  95. if(s[0] == '<' && s[1] == '=') { binary(Node::Type::LessThanEqual, 2, 6); continue; }
  96. if(s[0] == '>' && s[1] == '=') { binary(Node::Type::GreaterThanEqual, 2, 6); continue; }
  97. if(s[0] == '<') { binary(Node::Type::LessThan, 1, 6); continue; }
  98. if(s[0] == '>') { binary(Node::Type::GreaterThan, 1, 6); continue; }
  99. if(depth >= 5) break;
  100. if(s[0] == '&' && s[1] == '&') { binary(Node::Type::LogicalAnd, 2, 5); continue; }
  101. if(s[0] == '|' && s[1] == '|') { binary(Node::Type::LogicalOr, 2, 5); continue; }
  102. if(s[0] == '?' && s[1] == '?') { binary(Node::Type::Coalesce, 2, 4); continue; }
  103. if(s[0] == '?' && s[1] != '?') { ternary(Node::Type::Condition, 1, 4); continue; }
  104. if(depth >= 4) break;
  105. if(s[0] == '=') { binary(Node::Type::Assign, 1, 3); continue; }
  106. if(s[0] == ':' && s[1] == '=') { binary(Node::Type::Create, 2, 3); continue; }
  107. if(s[0] == '*' && s[1] == '=') { binary(Node::Type::AssignMultiply, 2, 3); continue; }
  108. if(s[0] == '/' && s[1] == '=') { binary(Node::Type::AssignDivide, 2, 3); continue; }
  109. if(s[0] == '%' && s[1] == '=') { binary(Node::Type::AssignModulo, 2, 3); continue; }
  110. if(s[0] == '+' && s[1] == '=') { binary(Node::Type::AssignAdd, 2, 3); continue; }
  111. if(s[0] == '-' && s[1] == '=') { binary(Node::Type::AssignSubtract, 2, 3); continue; }
  112. if(s[0] == '<' && s[1] == '<' && s[2] == '<' && s[3] == '=') { binary(Node::Type::AssignRotateLeft, 4, 3); continue; }
  113. if(s[0] == '>' && s[1] == '>' && s[2] == '>' && s[3] == '=') { binary(Node::Type::AssignRotateRight, 4, 3); continue; }
  114. if(s[0] == '<' && s[1] == '<' && s[2] == '=') { binary(Node::Type::AssignShiftLeft, 3, 3); continue; }
  115. if(s[0] == '>' && s[1] == '>' && s[2] == '=') { binary(Node::Type::AssignShiftRight, 3, 3); continue; }
  116. if(s[0] == '&' && s[1] == '=') { binary(Node::Type::AssignBitwiseAnd, 2, 3); continue; }
  117. if(s[0] == '|' && s[1] == '=') { binary(Node::Type::AssignBitwiseOr, 2, 3); continue; }
  118. if(s[0] == '^' && s[1] == '=') { binary(Node::Type::AssignBitwiseXor, 2, 3); continue; }
  119. if(s[0] == '~' && s[1] == '=') { binary(Node::Type::AssignConcatenate, 2, 3); continue; }
  120. if(depth >= 3) break;
  121. if(depth >= 2) break;
  122. if(s[0] == ',') { separator(Node::Type::Separator, 1, 2); continue; }
  123. if(depth >= 1 && (s[0] == ')' || s[0] == ']')) break;
  124. while(whitespace(s[0])) s++;
  125. if(!s[0]) break;
  126. throw "unrecognized terminal";
  127. }
  128. #undef p
  129. }
  130. inline auto parse(const string& expression) -> Node* {
  131. auto result = new Node;
  132. const char* p = expression;
  133. parse(result, p, 0);
  134. return result;
  135. }
  136. }