precedence.cpp 10 KB

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