precedence.cpp 9.5 KB

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