precedence.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "toolchain/parse/precedence.h"
  5. #include <initializer_list>
  6. #include <optional>
  7. #include "common/check.h"
  8. namespace Carbon::Parse {
  9. constexpr int8_t PrecedenceGroup::NumPrecedenceLevels = Lowest + 1;
  10. // A precomputed lookup table determining the relative precedence of two
  11. // precedence groups.
  12. struct PrecedenceGroup::OperatorPriorityTable {
  13. constexpr OperatorPriorityTable() : table() {
  14. // Start with a list of <higher precedence>, <lower precedence>
  15. // relationships.
  16. MarkHigherThan({Highest}, {TermPrefix, LogicalPrefix});
  17. MarkHigherThan({TermPrefix},
  18. {NumericPrefix, BitwisePrefix, IncrementDecrement});
  19. MarkHigherThan({NumericPrefix, BitwisePrefix, TypePostfix},
  20. {As, Multiplicative, Modulo, BitwiseAnd, BitwiseOr,
  21. BitwiseXor, BitShift});
  22. MarkHigherThan({Multiplicative}, {Additive});
  23. MarkHigherThan(
  24. {Additive, Modulo, BitwiseAnd, BitwiseOr, BitwiseXor, BitShift},
  25. {Relational, Where});
  26. MarkHigherThan({Relational, LogicalPrefix}, {LogicalAnd, LogicalOr});
  27. MarkHigherThan({As, LogicalAnd, LogicalOr, Where}, {Ref});
  28. MarkHigherThan({Ref}, {If});
  29. MarkHigherThan({If}, {Assignment});
  30. MarkHigherThan({Assignment, IncrementDecrement}, {Lowest});
  31. // Types are mostly a separate precedence graph.
  32. MarkHigherThan({Highest}, {TypePrefix});
  33. MarkHigherThan({TypePrefix}, {TypePostfix});
  34. // Compute the transitive closure of the above relationships: if we parse
  35. // `a $ b @ c` as `(a $ b) @ c` and parse `b @ c % d` as `(b @ c) % d`,
  36. // then we will parse `a $ b @ c % d` as `((a $ b) @ c) % d` and should
  37. // also parse `a $ bc % d` as `(a $ bc) % d`.
  38. MakeTransitivelyClosed();
  39. // Make the relation symmetric. If we parse `a $ b @ c` as `(a $ b) @ c`
  40. // then we want to parse `a @ b $ c` as `a @ (b $ c)`.
  41. MakeSymmetric();
  42. // Fill in the diagonal, which represents operator associativity.
  43. AddAssociativityRules();
  44. ConsistencyCheck();
  45. }
  46. constexpr auto MarkHigherThan(
  47. std::initializer_list<PrecedenceLevel> higher_group,
  48. std::initializer_list<PrecedenceLevel> lower_group) -> void {
  49. for (auto higher : higher_group) {
  50. for (auto lower : lower_group) {
  51. table[higher][lower] = OperatorPriority::LeftFirst;
  52. }
  53. }
  54. }
  55. constexpr auto MakeTransitivelyClosed() -> void {
  56. // A naive algorithm compiles acceptably fast for now (~0.5s). This should
  57. // be revisited if we see compile time problems after adding precedence
  58. // groups; it's easy to do this faster.
  59. bool changed = false;
  60. do {
  61. changed = false;
  62. // NOLINTNEXTLINE(modernize-loop-convert)
  63. for (int8_t a = 0; a != NumPrecedenceLevels; ++a) {
  64. for (int8_t b = 0; b != NumPrecedenceLevels; ++b) {
  65. if (table[a][b] == OperatorPriority::LeftFirst) {
  66. for (int8_t c = 0; c != NumPrecedenceLevels; ++c) {
  67. if (table[b][c] == OperatorPriority::LeftFirst &&
  68. table[a][c] != OperatorPriority::LeftFirst) {
  69. table[a][c] = OperatorPriority::LeftFirst;
  70. changed = true;
  71. }
  72. }
  73. }
  74. }
  75. }
  76. } while (changed);
  77. }
  78. constexpr auto MakeSymmetric() -> void {
  79. for (int8_t a = 0; a != NumPrecedenceLevels; ++a) {
  80. for (int8_t b = 0; b != NumPrecedenceLevels; ++b) {
  81. if (table[a][b] == OperatorPriority::LeftFirst) {
  82. CARBON_CHECK(table[b][a] != OperatorPriority::LeftFirst,
  83. "inconsistent lookup table entries");
  84. table[b][a] = OperatorPriority::RightFirst;
  85. }
  86. }
  87. }
  88. }
  89. constexpr auto AddAssociativityRules() -> void {
  90. // Associativity rules occupy the diagonal
  91. // For prefix operators, RightFirst would mean `@@x` is `@(@x)` and
  92. // Ambiguous would mean it's an error. LeftFirst is meaningless.
  93. for (PrecedenceLevel prefix : {TermPrefix, If}) {
  94. table[prefix][prefix] = OperatorPriority::RightFirst;
  95. }
  96. // Postfix operators are symmetric with prefix operators.
  97. for (PrecedenceLevel postfix : {TypePostfix}) {
  98. table[postfix][postfix] = OperatorPriority::LeftFirst;
  99. }
  100. // Traditionally-associative operators are given left-to-right
  101. // associativity.
  102. for (PrecedenceLevel assoc :
  103. {Multiplicative, Additive, BitwiseAnd, BitwiseOr, BitwiseXor,
  104. LogicalAnd, LogicalOr}) {
  105. table[assoc][assoc] = OperatorPriority::LeftFirst;
  106. }
  107. // For other operators, we require explicit parentheses.
  108. }
  109. constexpr auto ConsistencyCheck() -> void {
  110. for (int8_t level = 0; level != NumPrecedenceLevels; ++level) {
  111. if (level != Highest) {
  112. CARBON_CHECK(table[Highest][level] == OperatorPriority::LeftFirst &&
  113. table[level][Highest] == OperatorPriority::RightFirst,
  114. "Highest is not highest priority");
  115. }
  116. if (level != Lowest) {
  117. CARBON_CHECK(table[Lowest][level] == OperatorPriority::RightFirst &&
  118. table[level][Lowest] == OperatorPriority::LeftFirst,
  119. "Lowest is not lowest priority");
  120. }
  121. }
  122. }
  123. OperatorPriority table[NumPrecedenceLevels][NumPrecedenceLevels];
  124. };
  125. auto PrecedenceGroup::ForLeading(Lex::TokenKind kind)
  126. -> std::optional<PrecedenceGroup> {
  127. switch (kind) {
  128. case Lex::TokenKind::Star:
  129. case Lex::TokenKind::Amp:
  130. return PrecedenceGroup(TermPrefix);
  131. case Lex::TokenKind::Not:
  132. return PrecedenceGroup(LogicalPrefix);
  133. case Lex::TokenKind::Minus:
  134. return PrecedenceGroup(NumericPrefix);
  135. case Lex::TokenKind::MinusMinus:
  136. case Lex::TokenKind::PlusPlus:
  137. return PrecedenceGroup(IncrementDecrement);
  138. case Lex::TokenKind::Caret:
  139. return PrecedenceGroup(BitwisePrefix);
  140. case Lex::TokenKind::If:
  141. return PrecedenceGroup(If);
  142. case Lex::TokenKind::Ref:
  143. return PrecedenceGroup(Ref);
  144. case Lex::TokenKind::Const:
  145. case Lex::TokenKind::Partial:
  146. return PrecedenceGroup(TypePrefix);
  147. default:
  148. return std::nullopt;
  149. }
  150. }
  151. auto PrecedenceGroup::ForTrailing(Lex::TokenKind kind, bool infix)
  152. -> std::optional<Trailing> {
  153. switch (kind) {
  154. // Assignment operators.
  155. case Lex::TokenKind::Equal:
  156. case Lex::TokenKind::PlusEqual:
  157. case Lex::TokenKind::MinusEqual:
  158. case Lex::TokenKind::StarEqual:
  159. case Lex::TokenKind::SlashEqual:
  160. case Lex::TokenKind::PercentEqual:
  161. case Lex::TokenKind::AmpEqual:
  162. case Lex::TokenKind::PipeEqual:
  163. case Lex::TokenKind::CaretEqual:
  164. case Lex::TokenKind::GreaterGreaterEqual:
  165. case Lex::TokenKind::LessLessEqual:
  166. return Trailing{.level = Assignment, .is_binary = true};
  167. // Logical operators.
  168. case Lex::TokenKind::And:
  169. return Trailing{.level = LogicalAnd, .is_binary = true};
  170. case Lex::TokenKind::Or:
  171. return Trailing{.level = LogicalOr, .is_binary = true};
  172. // Bitwise operators.
  173. case Lex::TokenKind::Amp:
  174. return Trailing{.level = BitwiseAnd, .is_binary = true};
  175. case Lex::TokenKind::Pipe:
  176. return Trailing{.level = BitwiseOr, .is_binary = true};
  177. case Lex::TokenKind::Caret:
  178. return Trailing{.level = BitwiseXor, .is_binary = true};
  179. case Lex::TokenKind::GreaterGreater:
  180. case Lex::TokenKind::LessLess:
  181. return Trailing{.level = BitShift, .is_binary = true};
  182. // Relational operators.
  183. case Lex::TokenKind::EqualEqual:
  184. case Lex::TokenKind::ExclaimEqual:
  185. case Lex::TokenKind::Less:
  186. case Lex::TokenKind::LessEqual:
  187. case Lex::TokenKind::Greater:
  188. case Lex::TokenKind::GreaterEqual:
  189. case Lex::TokenKind::LessEqualGreater:
  190. return Trailing{.level = Relational, .is_binary = true};
  191. // Additive operators.
  192. case Lex::TokenKind::Plus:
  193. case Lex::TokenKind::Minus:
  194. return Trailing{.level = Additive, .is_binary = true};
  195. // Multiplicative operators.
  196. case Lex::TokenKind::Slash:
  197. return Trailing{.level = Multiplicative, .is_binary = true};
  198. case Lex::TokenKind::Percent:
  199. return Trailing{.level = Modulo, .is_binary = true};
  200. // `*` could be multiplication or pointer type formation.
  201. case Lex::TokenKind::Star:
  202. return infix ? Trailing{.level = Multiplicative, .is_binary = true}
  203. : Trailing{.level = TypePostfix, .is_binary = false};
  204. // Cast operator.
  205. case Lex::TokenKind::As:
  206. return Trailing{.level = As, .is_binary = true};
  207. // Requirement operator.
  208. case Lex::TokenKind::Where:
  209. return Trailing{.level = Where, .is_binary = true};
  210. // Prefix-only operators.
  211. case Lex::TokenKind::Const:
  212. case Lex::TokenKind::MinusMinus:
  213. case Lex::TokenKind::Not:
  214. case Lex::TokenKind::Partial:
  215. case Lex::TokenKind::PlusPlus:
  216. break;
  217. // Symbolic tokens that might be operators eventually.
  218. case Lex::TokenKind::Tilde:
  219. case Lex::TokenKind::Backslash:
  220. case Lex::TokenKind::Comma:
  221. case Lex::TokenKind::TildeEqual:
  222. case Lex::TokenKind::Exclaim:
  223. case Lex::TokenKind::LessGreater:
  224. case Lex::TokenKind::Colon:
  225. break;
  226. // Symbolic tokens that are intentionally not operators.
  227. case Lex::TokenKind::At:
  228. case Lex::TokenKind::LessMinus:
  229. case Lex::TokenKind::MinusGreater:
  230. case Lex::TokenKind::EqualGreater:
  231. case Lex::TokenKind::ColonEqual:
  232. case Lex::TokenKind::Period:
  233. case Lex::TokenKind::Semi:
  234. break;
  235. default:
  236. break;
  237. }
  238. return std::nullopt;
  239. }
  240. auto PrecedenceGroup::GetPriority(PrecedenceGroup left, PrecedenceGroup right)
  241. -> OperatorPriority {
  242. static constexpr OperatorPriorityTable Lookup;
  243. return Lookup.table[left.level_][right.level_];
  244. }
  245. } // namespace Carbon::Parse