parse_tree_test.cpp 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285
  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/parser/parse_tree.h"
  5. #include <gmock/gmock.h>
  6. #include <gtest/gtest.h>
  7. #include <forward_list>
  8. #include "common/ostream.h"
  9. #include "llvm/ADT/Sequence.h"
  10. #include "llvm/Support/FormatVariadic.h"
  11. #include "llvm/Support/SourceMgr.h"
  12. #include "toolchain/common/yaml_test_helpers.h"
  13. #include "toolchain/diagnostics/diagnostic_emitter.h"
  14. #include "toolchain/diagnostics/mocks.h"
  15. #include "toolchain/lexer/tokenized_buffer.h"
  16. #include "toolchain/parser/parse_node_kind.h"
  17. #include "toolchain/parser/parse_test_helpers.h"
  18. namespace Carbon::Testing {
  19. namespace {
  20. using ::testing::AtLeast;
  21. using ::testing::ElementsAre;
  22. using ::testing::Eq;
  23. using ::testing::Ne;
  24. using ::testing::StrEq;
  25. class ParseTreeTest : public ::testing::Test {
  26. protected:
  27. auto GetSourceBuffer(llvm::Twine t) -> SourceBuffer& {
  28. source_storage.push_front(
  29. std::move(*SourceBuffer::CreateFromText(t.str())));
  30. return source_storage.front();
  31. }
  32. auto GetTokenizedBuffer(llvm::Twine t) -> TokenizedBuffer& {
  33. token_storage.push_front(
  34. TokenizedBuffer::Lex(GetSourceBuffer(t), consumer));
  35. return token_storage.front();
  36. }
  37. std::forward_list<SourceBuffer> source_storage;
  38. std::forward_list<TokenizedBuffer> token_storage;
  39. DiagnosticConsumer& consumer = ConsoleDiagnosticConsumer();
  40. };
  41. TEST_F(ParseTreeTest, Empty) {
  42. TokenizedBuffer tokens = GetTokenizedBuffer("");
  43. ParseTree tree = ParseTree::Parse(tokens, consumer);
  44. EXPECT_FALSE(tree.HasErrors());
  45. EXPECT_THAT(tree, MatchParseTreeNodes({MatchFileEnd()}));
  46. }
  47. TEST_F(ParseTreeTest, EmptyDeclaration) {
  48. TokenizedBuffer tokens = GetTokenizedBuffer(";");
  49. ParseTree tree = ParseTree::Parse(tokens, consumer);
  50. EXPECT_FALSE(tree.HasErrors());
  51. auto it = tree.Postorder().begin();
  52. auto end = tree.Postorder().end();
  53. ASSERT_THAT(it, Ne(end));
  54. ParseTree::Node n = *it++;
  55. ASSERT_THAT(it, Ne(end));
  56. ParseTree::Node eof = *it++;
  57. EXPECT_THAT(it, Eq(end));
  58. // Directly test the main API so that we get easier to understand errors in
  59. // simple cases than what the custom matcher will produce.
  60. EXPECT_FALSE(tree.HasErrorInNode(n));
  61. EXPECT_FALSE(tree.HasErrorInNode(eof));
  62. EXPECT_THAT(tree.GetNodeKind(n), Eq(ParseNodeKind::EmptyDeclaration()));
  63. EXPECT_THAT(tree.GetNodeKind(eof), Eq(ParseNodeKind::FileEnd()));
  64. auto t = tree.GetNodeToken(n);
  65. ASSERT_THAT(tokens.tokens().begin(), Ne(tokens.tokens().end()));
  66. EXPECT_THAT(t, Eq(*tokens.tokens().begin()));
  67. EXPECT_THAT(tokens.GetTokenText(t), Eq(";"));
  68. EXPECT_THAT(tree.Children(n).begin(), Eq(tree.Children(n).end()));
  69. EXPECT_THAT(tree.Children(eof).begin(), Eq(tree.Children(eof).end()));
  70. EXPECT_THAT(tree.Postorder().begin(), Eq(tree.Postorder(n).begin()));
  71. EXPECT_THAT(tree.Postorder(n).end(), Eq(tree.Postorder(eof).begin()));
  72. EXPECT_THAT(tree.Postorder(eof).end(), Eq(tree.Postorder().end()));
  73. }
  74. TEST_F(ParseTreeTest, BasicFunctionDeclaration) {
  75. TokenizedBuffer tokens = GetTokenizedBuffer("fn F();");
  76. ParseTree tree = ParseTree::Parse(tokens, consumer);
  77. EXPECT_FALSE(tree.HasErrors());
  78. EXPECT_THAT(tree, MatchParseTreeNodes(
  79. {MatchFunctionDeclaration("fn", MatchDeclaredName("F"),
  80. MatchParameters(),
  81. MatchDeclarationEnd(";")),
  82. MatchFileEnd()}));
  83. }
  84. TEST_F(ParseTreeTest, NoDeclarationIntroducerOrSemi) {
  85. TokenizedBuffer tokens = GetTokenizedBuffer("foo bar baz");
  86. ParseTree tree = ParseTree::Parse(tokens, consumer);
  87. EXPECT_TRUE(tree.HasErrors());
  88. EXPECT_THAT(tree, MatchParseTreeNodes({MatchFileEnd()}));
  89. }
  90. TEST_F(ParseTreeTest, NoDeclarationIntroducerWithSemi) {
  91. TokenizedBuffer tokens = GetTokenizedBuffer("foo;");
  92. ParseTree tree = ParseTree::Parse(tokens, consumer);
  93. EXPECT_TRUE(tree.HasErrors());
  94. EXPECT_THAT(tree, MatchParseTreeNodes({MatchEmptyDeclaration(";", HasError),
  95. MatchFileEnd()}));
  96. }
  97. TEST_F(ParseTreeTest, JustFunctionIntroducerAndSemi) {
  98. TokenizedBuffer tokens = GetTokenizedBuffer("fn;");
  99. ParseTree tree = ParseTree::Parse(tokens, consumer);
  100. EXPECT_TRUE(tree.HasErrors());
  101. EXPECT_THAT(tree, MatchParseTreeNodes({MatchFunctionDeclaration(
  102. HasError, MatchDeclarationEnd()),
  103. MatchFileEnd()}));
  104. }
  105. TEST_F(ParseTreeTest, RepeatedFunctionIntroducerAndSemi) {
  106. TokenizedBuffer tokens = GetTokenizedBuffer("fn fn;");
  107. ParseTree tree = ParseTree::Parse(tokens, consumer);
  108. EXPECT_TRUE(tree.HasErrors());
  109. EXPECT_THAT(tree, MatchParseTreeNodes({MatchFunctionDeclaration(
  110. HasError, MatchDeclarationEnd()),
  111. MatchFileEnd()}));
  112. }
  113. TEST_F(ParseTreeTest, FunctionDeclarationWithNoSignatureOrSemi) {
  114. TokenizedBuffer tokens = GetTokenizedBuffer("fn foo");
  115. ParseTree tree = ParseTree::Parse(tokens, consumer);
  116. EXPECT_TRUE(tree.HasErrors());
  117. EXPECT_THAT(tree,
  118. MatchParseTreeNodes(
  119. {MatchFunctionDeclaration(HasError, MatchDeclaredName("foo")),
  120. MatchFileEnd()}));
  121. }
  122. TEST_F(ParseTreeTest,
  123. FunctionDeclarationWithIdentifierInsteadOfSignatureAndSemi) {
  124. TokenizedBuffer tokens = GetTokenizedBuffer("fn foo bar;");
  125. ParseTree tree = ParseTree::Parse(tokens, consumer);
  126. EXPECT_TRUE(tree.HasErrors());
  127. EXPECT_THAT(tree, MatchParseTreeNodes({MatchFunctionDeclaration(
  128. HasError, MatchDeclaredName("foo"),
  129. MatchDeclarationEnd()),
  130. MatchFileEnd()}));
  131. }
  132. TEST_F(ParseTreeTest, FunctionDeclarationWithParameterList) {
  133. TokenizedBuffer tokens = GetTokenizedBuffer("fn foo(bar: i32, baz: i32);");
  134. ParseTree tree = ParseTree::Parse(tokens, consumer);
  135. EXPECT_FALSE(tree.HasErrors());
  136. EXPECT_THAT(
  137. tree,
  138. MatchParseTreeNodes(
  139. {MatchFunctionDeclaration(
  140. MatchDeclaredName("foo"),
  141. MatchParameterList(MatchPatternBinding(MatchDeclaredName("bar"),
  142. ":", MatchLiteral("i32")),
  143. MatchParameterListComma(),
  144. MatchPatternBinding(MatchDeclaredName("baz"),
  145. ":", MatchLiteral("i32")),
  146. MatchParameterListEnd()),
  147. MatchDeclarationEnd()),
  148. MatchFileEnd()}));
  149. }
  150. TEST_F(ParseTreeTest, FunctionDefinitionWithParameterList) {
  151. TokenizedBuffer tokens = GetTokenizedBuffer(
  152. "fn foo(bar: i64, baz: i64) {\n"
  153. " foo(baz, bar + baz);\n"
  154. "}");
  155. ParseTree tree = ParseTree::Parse(tokens, consumer);
  156. EXPECT_FALSE(tree.HasErrors());
  157. EXPECT_THAT(
  158. tree,
  159. MatchParseTreeNodes(
  160. {MatchFunctionDeclaration(
  161. MatchDeclaredName("foo"),
  162. MatchParameterList(MatchPatternBinding(MatchDeclaredName("bar"),
  163. ":", MatchLiteral("i64")),
  164. MatchParameterListComma(),
  165. MatchPatternBinding(MatchDeclaredName("baz"),
  166. ":", MatchLiteral("i64")),
  167. MatchParameterListEnd()),
  168. MatchCodeBlock(
  169. MatchExpressionStatement(MatchCallExpression(
  170. MatchNameReference("foo"), MatchNameReference("baz"),
  171. MatchCallExpressionComma(),
  172. MatchInfixOperator(MatchNameReference("bar"), "+",
  173. MatchNameReference("baz")),
  174. MatchCallExpressionEnd())),
  175. MatchCodeBlockEnd())),
  176. MatchFileEnd()}));
  177. }
  178. TEST_F(ParseTreeTest, FunctionDeclarationWithReturnType) {
  179. TokenizedBuffer tokens = GetTokenizedBuffer("fn foo() -> u32;");
  180. ParseTree tree = ParseTree::Parse(tokens, consumer);
  181. EXPECT_FALSE(tree.HasErrors());
  182. EXPECT_THAT(
  183. tree,
  184. MatchParseTreeNodes(
  185. {MatchFunctionDeclaration(MatchDeclaredName("foo"), MatchParameters(),
  186. MatchReturnType(MatchLiteral("u32")),
  187. MatchDeclarationEnd()),
  188. MatchFileEnd()}));
  189. }
  190. TEST_F(ParseTreeTest, FunctionDefinitionWithReturnType) {
  191. TokenizedBuffer tokens = GetTokenizedBuffer(
  192. "fn foo() -> f64 {\n"
  193. " return 42;\n"
  194. "}");
  195. ParseTree tree = ParseTree::Parse(tokens, consumer);
  196. EXPECT_FALSE(tree.HasErrors());
  197. EXPECT_THAT(tree,
  198. MatchParseTreeNodes(
  199. {MatchFunctionDeclaration(
  200. MatchDeclaredName("foo"), MatchParameters(),
  201. MatchReturnType(MatchLiteral("f64")),
  202. MatchCodeBlock(MatchReturnStatement(MatchLiteral("42"),
  203. MatchStatementEnd()),
  204. MatchCodeBlockEnd())),
  205. MatchFileEnd()}));
  206. }
  207. TEST_F(ParseTreeTest, FunctionDeclarationWithSingleIdentifierParameterList) {
  208. TokenizedBuffer tokens = GetTokenizedBuffer("fn foo(bar);");
  209. ParseTree tree = ParseTree::Parse(tokens, consumer);
  210. // Note: this might become valid depending on the parameter syntax, this test
  211. // shouldn't be taken as a sign it should remain invalid.
  212. EXPECT_TRUE(tree.HasErrors());
  213. EXPECT_THAT(tree,
  214. MatchParseTreeNodes(
  215. {MatchFunctionDeclaration(
  216. MatchDeclaredName("foo"),
  217. MatchParameterList(HasError, MatchParameterListEnd()),
  218. MatchDeclarationEnd()),
  219. MatchFileEnd()}));
  220. }
  221. TEST_F(ParseTreeTest, FunctionDeclarationWithoutName) {
  222. TokenizedBuffer tokens = GetTokenizedBuffer("fn ();");
  223. ParseTree tree = ParseTree::Parse(tokens, consumer);
  224. EXPECT_TRUE(tree.HasErrors());
  225. EXPECT_THAT(tree, MatchParseTreeNodes({MatchFunctionDeclaration(
  226. HasError, MatchDeclarationEnd()),
  227. MatchFileEnd()}));
  228. }
  229. TEST_F(ParseTreeTest,
  230. FunctionDeclarationWithoutNameAndManyTokensToSkipInGroupedSymbols) {
  231. TokenizedBuffer tokens = GetTokenizedBuffer(
  232. "fn (a tokens c d e f g h i j k l m n o p q r s t u v w x y z);");
  233. ParseTree tree = ParseTree::Parse(tokens, consumer);
  234. EXPECT_TRUE(tree.HasErrors());
  235. EXPECT_THAT(tree, MatchParseTreeNodes({MatchFunctionDeclaration(
  236. HasError, MatchDeclarationEnd()),
  237. MatchFileEnd()}));
  238. }
  239. TEST_F(ParseTreeTest, FunctionDeclarationSkipToNewlineWithoutSemi) {
  240. TokenizedBuffer tokens = GetTokenizedBuffer(
  241. "fn ()\n"
  242. "fn F();");
  243. ParseTree tree = ParseTree::Parse(tokens, consumer);
  244. EXPECT_TRUE(tree.HasErrors());
  245. EXPECT_THAT(
  246. tree, MatchParseTreeNodes({MatchFunctionDeclaration(HasError),
  247. MatchFunctionDeclaration(
  248. MatchDeclaredName("F"), MatchParameters(),
  249. MatchDeclarationEnd()),
  250. MatchFileEnd()}));
  251. }
  252. TEST_F(ParseTreeTest, FunctionDeclarationSkipIndentedNewlineWithSemi) {
  253. TokenizedBuffer tokens = GetTokenizedBuffer(
  254. "fn (x,\n"
  255. " y,\n"
  256. " z);\n"
  257. "fn F();");
  258. ParseTree tree = ParseTree::Parse(tokens, consumer);
  259. EXPECT_TRUE(tree.HasErrors());
  260. EXPECT_THAT(
  261. tree,
  262. MatchParseTreeNodes(
  263. {MatchFunctionDeclaration(HasError, MatchDeclarationEnd()),
  264. MatchFunctionDeclaration(MatchDeclaredName("F"), MatchParameters(),
  265. MatchDeclarationEnd()),
  266. MatchFileEnd()}));
  267. }
  268. TEST_F(ParseTreeTest, FunctionDeclarationSkipIndentedNewlineWithoutSemi) {
  269. TokenizedBuffer tokens = GetTokenizedBuffer(
  270. "fn (x,\n"
  271. " y,\n"
  272. " z)\n"
  273. "fn F();");
  274. ParseTree tree = ParseTree::Parse(tokens, consumer);
  275. EXPECT_TRUE(tree.HasErrors());
  276. EXPECT_THAT(
  277. tree, MatchParseTreeNodes({MatchFunctionDeclaration(HasError),
  278. MatchFunctionDeclaration(
  279. MatchDeclaredName("F"), MatchParameters(),
  280. MatchDeclarationEnd()),
  281. MatchFileEnd()}));
  282. }
  283. TEST_F(ParseTreeTest, FunctionDeclarationSkipIndentedNewlineUntilOutdent) {
  284. TokenizedBuffer tokens = GetTokenizedBuffer(
  285. " fn (x,\n"
  286. " y,\n"
  287. " z)\n"
  288. "fn F();");
  289. ParseTree tree = ParseTree::Parse(tokens, consumer);
  290. EXPECT_TRUE(tree.HasErrors());
  291. EXPECT_THAT(
  292. tree, MatchParseTreeNodes({MatchFunctionDeclaration(HasError),
  293. MatchFunctionDeclaration(
  294. MatchDeclaredName("F"), MatchParameters(),
  295. MatchDeclarationEnd()),
  296. MatchFileEnd()}));
  297. }
  298. TEST_F(ParseTreeTest, FunctionDeclarationSkipWithoutSemiToCurly) {
  299. // FIXME: We don't have a grammar construct that uses curlies yet so this just
  300. // won't parse at all. Once it does, we should ensure that the close brace
  301. // gets properly parsed for the struct (or whatever other curly-braced syntax
  302. // we have grouping function declarations) despite the invalid function
  303. // declaration missing a semicolon.
  304. TokenizedBuffer tokens = GetTokenizedBuffer(
  305. "struct X { fn () }\n"
  306. "fn F();");
  307. ParseTree tree = ParseTree::Parse(tokens, consumer);
  308. EXPECT_TRUE(tree.HasErrors());
  309. }
  310. TEST_F(ParseTreeTest, BasicFunctionDefinition) {
  311. TokenizedBuffer tokens = GetTokenizedBuffer(
  312. "fn F() {\n"
  313. "}");
  314. ParseTree tree = ParseTree::Parse(tokens, consumer);
  315. EXPECT_FALSE(tree.HasErrors());
  316. EXPECT_THAT(tree, MatchParseTreeNodes(
  317. {MatchFunctionDeclaration(
  318. MatchDeclaredName("F"), MatchParameters(),
  319. MatchCodeBlock("{", MatchCodeBlockEnd("}"))),
  320. MatchFileEnd()}));
  321. }
  322. TEST_F(ParseTreeTest, FunctionDefinitionWithIdenifierInStatements) {
  323. TokenizedBuffer tokens = GetTokenizedBuffer(
  324. "fn F() {\n"
  325. " bar\n"
  326. "}");
  327. ParseTree tree = ParseTree::Parse(tokens, consumer);
  328. // Note: this might become valid depending on the expression syntax. This test
  329. // shouldn't be taken as a sign it should remain invalid.
  330. EXPECT_TRUE(tree.HasErrors());
  331. EXPECT_THAT(tree, MatchParseTreeNodes(
  332. {MatchFunctionDeclaration(
  333. MatchDeclaredName("F"), MatchParameters(),
  334. MatchCodeBlock(HasError, MatchNameReference("bar"),
  335. MatchCodeBlockEnd())),
  336. MatchFileEnd()}));
  337. }
  338. TEST_F(ParseTreeTest, FunctionDefinitionWithFunctionCall) {
  339. TokenizedBuffer tokens = GetTokenizedBuffer(
  340. "fn F() {\n"
  341. " a.b.f(c.d, (e)).g();\n"
  342. "}");
  343. ParseTree tree = ParseTree::Parse(tokens, consumer);
  344. EXPECT_FALSE(tree.HasErrors());
  345. ExpectedNode call_to_f = MatchCallExpression(
  346. MatchDesignator(MatchDesignator(MatchNameReference("a"), "b"), "f"),
  347. MatchDesignator(MatchNameReference("c"), "d"), MatchCallExpressionComma(),
  348. MatchParenExpression(MatchNameReference("e"), MatchParenExpressionEnd()),
  349. MatchCallExpressionEnd());
  350. ExpectedNode statement = MatchExpressionStatement(MatchCallExpression(
  351. MatchDesignator(call_to_f, "g"), MatchCallExpressionEnd()));
  352. EXPECT_THAT(tree, MatchParseTreeNodes(
  353. {MatchFunctionWithBody(statement), MatchFileEnd()}));
  354. }
  355. TEST_F(ParseTreeTest, InvalidDesignators) {
  356. TokenizedBuffer tokens = GetTokenizedBuffer(
  357. "fn F() {\n"
  358. " a.;\n"
  359. " a.fn;\n"
  360. " a.42;\n"
  361. "}");
  362. ParseTree tree = ParseTree::Parse(tokens, consumer);
  363. EXPECT_TRUE(tree.HasErrors());
  364. EXPECT_THAT(tree, MatchParseTreeNodes(
  365. {MatchFunctionWithBody(
  366. MatchExpressionStatement(
  367. MatchDesignatorExpression(
  368. MatchNameReference("a"), ".", HasError),
  369. HasError, ";"),
  370. MatchExpressionStatement(
  371. MatchDesignatorExpression(
  372. MatchNameReference("a"), ".",
  373. MatchDesignatedName("fn", HasError)),
  374. ";"),
  375. MatchExpressionStatement(
  376. MatchDesignatorExpression(
  377. MatchNameReference("a"), ".", HasError),
  378. HasError, ";")),
  379. MatchFileEnd()}));
  380. }
  381. TEST_F(ParseTreeTest, Operators) {
  382. TokenizedBuffer tokens = GetTokenizedBuffer(
  383. "fn F() {\n"
  384. " n = a * b + c * d = d * d << e & f - not g;\n"
  385. "}");
  386. ParseTree tree = ParseTree::Parse(tokens, consumer);
  387. EXPECT_TRUE(tree.HasErrors());
  388. EXPECT_THAT(
  389. tree,
  390. MatchParseTreeNodes(
  391. {MatchFunctionWithBody(MatchExpressionStatement(MatchInfixOperator(
  392. MatchNameReference("n"), "=",
  393. MatchInfixOperator(
  394. MatchInfixOperator(
  395. MatchInfixOperator(MatchNameReference("a"), "*",
  396. MatchNameReference("b")),
  397. "+",
  398. MatchInfixOperator(MatchNameReference("c"), "*",
  399. MatchNameReference("d"))),
  400. "=",
  401. MatchInfixOperator(
  402. HasError,
  403. MatchInfixOperator(
  404. HasError,
  405. MatchInfixOperator(
  406. HasError,
  407. MatchInfixOperator(MatchNameReference("d"), "*",
  408. MatchNameReference("d")),
  409. "<<", MatchNameReference("e")),
  410. "&", MatchNameReference("f")),
  411. "-",
  412. MatchPrefixOperator("not", MatchNameReference("g"))))))),
  413. MatchFileEnd()}));
  414. }
  415. TEST_F(ParseTreeTest, OperatorsPrefixUnary) {
  416. TokenizedBuffer tokens = GetTokenizedBuffer(
  417. "fn F() {\n"
  418. " ++++n;\n"
  419. "}");
  420. ParseTree tree = ParseTree::Parse(tokens, consumer);
  421. EXPECT_FALSE(tree.HasErrors());
  422. EXPECT_THAT(
  423. tree,
  424. MatchParseTreeNodes(
  425. {MatchFunctionWithBody(MatchExpressionStatement(MatchPrefixOperator(
  426. "++", MatchPrefixOperator("++", MatchNameReference("n"))))),
  427. MatchFileEnd()}));
  428. }
  429. TEST_F(ParseTreeTest, OperatorsPostfixUnary) {
  430. TokenizedBuffer tokens = GetTokenizedBuffer(
  431. "fn F() {\n"
  432. " n++++;\n"
  433. "}");
  434. ParseTree tree = ParseTree::Parse(tokens, consumer);
  435. EXPECT_FALSE(tree.HasErrors());
  436. EXPECT_THAT(
  437. tree,
  438. MatchParseTreeNodes(
  439. {MatchFunctionWithBody(MatchExpressionStatement(MatchPostfixOperator(
  440. MatchPostfixOperator(MatchNameReference("n"), "++"), "++"))),
  441. MatchFileEnd()}));
  442. }
  443. TEST_F(ParseTreeTest, OperatorsAssociative) {
  444. TokenizedBuffer tokens = GetTokenizedBuffer(
  445. "fn F() {\n"
  446. " a and b and c;\n"
  447. "}");
  448. ParseTree tree = ParseTree::Parse(tokens, consumer);
  449. EXPECT_FALSE(tree.HasErrors());
  450. EXPECT_THAT(
  451. tree,
  452. MatchParseTreeNodes(
  453. {MatchFunctionWithBody(MatchExpressionStatement(MatchInfixOperator(
  454. MatchInfixOperator(MatchNameReference("a"), "and",
  455. MatchNameReference("b")),
  456. "and", MatchNameReference("c")))),
  457. MatchFileEnd()}));
  458. }
  459. TEST_F(ParseTreeTest, OperatorsMissingPrecedence1) {
  460. TokenizedBuffer tokens = GetTokenizedBuffer(
  461. "fn F() {\n"
  462. " a and b or c;\n"
  463. "}");
  464. ParseTree tree = ParseTree::Parse(tokens, consumer);
  465. EXPECT_TRUE(tree.HasErrors());
  466. EXPECT_THAT(
  467. tree,
  468. MatchParseTreeNodes(
  469. {MatchFunctionWithBody(MatchExpressionStatement(MatchInfixOperator(
  470. HasError,
  471. MatchInfixOperator(MatchNameReference("a"), "and",
  472. MatchNameReference("b")),
  473. "or", MatchNameReference("c")))),
  474. MatchFileEnd()}));
  475. }
  476. TEST_F(ParseTreeTest, OperatorsMissingPrecedence2) {
  477. TokenizedBuffer tokens = GetTokenizedBuffer(
  478. "fn F() {\n"
  479. " a or b and c;\n"
  480. "}");
  481. ParseTree tree = ParseTree::Parse(tokens, consumer);
  482. EXPECT_TRUE(tree.HasErrors());
  483. EXPECT_THAT(
  484. tree,
  485. MatchParseTreeNodes(
  486. {MatchFunctionWithBody(MatchExpressionStatement(MatchInfixOperator(
  487. HasError,
  488. MatchInfixOperator(MatchNameReference("a"), "or",
  489. MatchNameReference("b")),
  490. "and", MatchNameReference("c")))),
  491. MatchFileEnd()}));
  492. }
  493. TEST_F(ParseTreeTest, OperatorsMissingPrecedenceForNot) {
  494. TokenizedBuffer tokens = GetTokenizedBuffer(
  495. "fn F() {\n"
  496. " not a and not b and not c;\n"
  497. "}");
  498. ParseTree tree = ParseTree::Parse(tokens, consumer);
  499. EXPECT_FALSE(tree.HasErrors());
  500. EXPECT_THAT(
  501. tree,
  502. MatchParseTreeNodes(
  503. {MatchFunctionWithBody(MatchExpressionStatement(MatchInfixOperator(
  504. MatchInfixOperator(
  505. MatchPrefixOperator("not", MatchNameReference("a")), "and",
  506. MatchPrefixOperator("not", MatchNameReference("b"))),
  507. "and", MatchPrefixOperator("not", MatchNameReference("c"))))),
  508. MatchFileEnd()}));
  509. }
  510. TEST_F(ParseTreeTest, OperatorFixity) {
  511. TokenizedBuffer tokens = GetTokenizedBuffer(
  512. "fn F(p: i32*, n: i32) {\n"
  513. " var q: i32* = p;\n"
  514. " var t: Type = i32*;\n"
  515. " t = t**;\n"
  516. " n = n * n;\n"
  517. " n = n * *p;\n"
  518. " n = n*n;\n"
  519. " G(i32*, n * n);\n"
  520. "}");
  521. ParseTree tree = ParseTree::Parse(tokens, consumer);
  522. EXPECT_FALSE(tree.HasErrors());
  523. EXPECT_THAT(
  524. tree,
  525. MatchParseTreeNodes(
  526. {MatchFunctionDeclaration(
  527. MatchDeclaredName("F"),
  528. MatchParameters(
  529. MatchPatternBinding(
  530. MatchDeclaredName("p"),
  531. MatchPostfixOperator(MatchLiteral("i32"), "*")),
  532. MatchParameterListComma(),
  533. MatchPatternBinding(MatchDeclaredName("n"),
  534. MatchLiteral("i32"))),
  535. MatchCodeBlock(
  536. MatchVariableDeclaration(
  537. MatchPatternBinding(
  538. MatchDeclaredName("q"),
  539. MatchPostfixOperator(MatchLiteral("i32"), "*")),
  540. MatchVariableInitializer(MatchNameReference("p")),
  541. MatchDeclarationEnd()),
  542. MatchVariableDeclaration(
  543. MatchPatternBinding(MatchDeclaredName("t"),
  544. MatchNameReference("Type")),
  545. MatchVariableInitializer(
  546. MatchPostfixOperator(MatchLiteral("i32"), "*")),
  547. MatchDeclarationEnd()),
  548. MatchExpressionStatement(MatchInfixOperator(
  549. MatchNameReference("t"), "=",
  550. MatchPostfixOperator(
  551. MatchPostfixOperator(MatchNameReference("t"), "*"),
  552. "*"))),
  553. MatchExpressionStatement(MatchInfixOperator(
  554. MatchNameReference("n"), "=",
  555. MatchInfixOperator(MatchNameReference("n"), "*",
  556. MatchNameReference("n")))),
  557. MatchExpressionStatement(MatchInfixOperator(
  558. MatchNameReference("n"), "=",
  559. MatchInfixOperator(
  560. MatchNameReference("n"), "*",
  561. MatchPrefixOperator("*", MatchNameReference("p"))))),
  562. MatchExpressionStatement(MatchInfixOperator(
  563. MatchNameReference("n"), "=",
  564. MatchInfixOperator(MatchNameReference("n"), "*",
  565. MatchNameReference("n")))),
  566. MatchExpressionStatement(MatchCallExpression(
  567. MatchNameReference("G"),
  568. MatchPostfixOperator(MatchLiteral("i32"), "*"),
  569. MatchCallExpressionComma(),
  570. MatchInfixOperator(MatchNameReference("n"), "*",
  571. MatchNameReference("n")),
  572. MatchCallExpressionEnd())),
  573. MatchCodeBlockEnd())),
  574. MatchFileEnd()}));
  575. }
  576. TEST_F(ParseTreeTest, OperatorWhitespaceErrors) {
  577. // Test dispositions: Recovered means we issued an error but recovered a
  578. // proper parse tree; Failed means we didn't fully recover from the error.
  579. enum Kind { Valid, Recovered, Failed };
  580. struct Testcase {
  581. const char* input;
  582. Kind kind;
  583. } testcases[] = {
  584. {"var v: Type = i8*;", Valid},
  585. {"var v: Type = i8 *;", Recovered},
  586. {"var v: Type = i8* ;", Valid},
  587. {"var v: Type = i8 * ;", Recovered},
  588. {"var n: i8 = n * n;", Valid},
  589. {"var n: i8 = n*n;", Valid},
  590. {"var n: i8 = (n)*3;", Valid},
  591. {"var n: i8 = 3*(n);", Valid},
  592. {"var n: i8 = n *n;", Recovered},
  593. // FIXME: We could figure out that this first Failed example is infix
  594. // with one-token lookahead.
  595. {"var n: i8 = n* n;", Failed},
  596. {"var n: i8 = n* -n;", Failed},
  597. {"var n: i8 = n* *p;", Failed},
  598. // FIXME: We try to form (n*)*p and reject due to missing parentheses
  599. // before we notice the missing whitespace around the second `*`.
  600. // It'd be better to (somehow) form n*(*p) and reject due to the missing
  601. // whitespace around the first `*`.
  602. {"var n: i8 = n**p;", Failed},
  603. {"var n: i8 = -n;", Valid},
  604. {"var n: i8 = - n;", Recovered},
  605. {"var n: i8 =-n;", Valid},
  606. {"var n: i8 =- n;", Recovered},
  607. {"var n: i8 = F(i8 *);", Recovered},
  608. {"var n: i8 = F(i8 *, 0);", Recovered},
  609. };
  610. for (auto [input, kind] : testcases) {
  611. TokenizedBuffer tokens = GetTokenizedBuffer(input);
  612. ErrorTrackingDiagnosticConsumer error_tracker(consumer);
  613. ParseTree tree = ParseTree::Parse(tokens, error_tracker);
  614. EXPECT_THAT(tree.HasErrors(), Eq(kind == Failed)) << input;
  615. EXPECT_THAT(error_tracker.SeenError(), Eq(kind != Valid)) << input;
  616. }
  617. }
  618. TEST_F(ParseTreeTest, VariableDeclarations) {
  619. TokenizedBuffer tokens = GetTokenizedBuffer(
  620. "var v: i32 = 0;\n"
  621. "var w: i32;\n"
  622. "fn F() {\n"
  623. " var s: String = \"hello\";\n"
  624. "}");
  625. ParseTree tree = ParseTree::Parse(tokens, consumer);
  626. EXPECT_FALSE(tree.HasErrors());
  627. EXPECT_THAT(tree,
  628. MatchParseTreeNodes(
  629. {MatchVariableDeclaration(
  630. MatchPatternBinding(MatchDeclaredName("v"), ":",
  631. MatchLiteral("i32")),
  632. MatchVariableInitializer(MatchLiteral("0")),
  633. MatchDeclarationEnd()),
  634. MatchVariableDeclaration(
  635. MatchPatternBinding(MatchDeclaredName("w"), ":",
  636. MatchLiteral("i32")),
  637. MatchDeclarationEnd()),
  638. MatchFunctionWithBody(MatchVariableDeclaration(
  639. MatchPatternBinding(MatchDeclaredName("s"), ":",
  640. MatchNameReference("String")),
  641. MatchVariableInitializer(MatchLiteral("\"hello\"")),
  642. MatchDeclarationEnd())),
  643. MatchFileEnd()}));
  644. }
  645. TEST_F(ParseTreeTest, IfNoElse) {
  646. TokenizedBuffer tokens = GetTokenizedBuffer(
  647. "fn F() {\n"
  648. " if (a) {\n"
  649. " if (b) {\n"
  650. " if (c) {\n"
  651. " d;\n"
  652. " }\n"
  653. " }\n"
  654. " }\n"
  655. "}");
  656. ErrorTrackingDiagnosticConsumer error_tracker(consumer);
  657. ParseTree tree = ParseTree::Parse(tokens, error_tracker);
  658. EXPECT_FALSE(tree.HasErrors());
  659. EXPECT_FALSE(error_tracker.SeenError());
  660. EXPECT_THAT(
  661. tree,
  662. MatchParseTreeNodes(
  663. {MatchFunctionWithBody(MatchIfStatement(
  664. MatchCondition(MatchNameReference("a"), MatchConditionEnd()),
  665. MatchCodeBlock(
  666. MatchIfStatement(
  667. MatchCondition(MatchNameReference("b"),
  668. MatchConditionEnd()),
  669. MatchCodeBlock(
  670. MatchIfStatement(
  671. MatchCondition(MatchNameReference("c"),
  672. MatchConditionEnd()),
  673. MatchCodeBlock(MatchExpressionStatement(
  674. MatchNameReference("d")),
  675. MatchCodeBlockEnd())),
  676. MatchCodeBlockEnd())),
  677. MatchCodeBlockEnd()))),
  678. MatchFileEnd()}));
  679. }
  680. TEST_F(ParseTreeTest, IfNoElseUnbraced) {
  681. TokenizedBuffer tokens = GetTokenizedBuffer(
  682. "fn F() {\n"
  683. " if (a)\n"
  684. " if (b)\n"
  685. " if (c)\n"
  686. " d;\n"
  687. "}");
  688. ErrorTrackingDiagnosticConsumer error_tracker(consumer);
  689. ParseTree tree = ParseTree::Parse(tokens, error_tracker);
  690. // The missing braces are invalid, but we should be able to recover.
  691. EXPECT_FALSE(tree.HasErrors());
  692. EXPECT_TRUE(error_tracker.SeenError());
  693. EXPECT_THAT(
  694. tree,
  695. MatchParseTreeNodes(
  696. {MatchFunctionWithBody(MatchIfStatement(
  697. MatchCondition(MatchNameReference("a"), MatchConditionEnd()),
  698. MatchIfStatement(
  699. MatchCondition(MatchNameReference("b"), MatchConditionEnd()),
  700. MatchIfStatement(
  701. MatchCondition(MatchNameReference("c"),
  702. MatchConditionEnd()),
  703. MatchExpressionStatement(MatchNameReference("d")))))),
  704. MatchFileEnd()}));
  705. }
  706. TEST_F(ParseTreeTest, IfElse) {
  707. TokenizedBuffer tokens = GetTokenizedBuffer(
  708. "fn F() {\n"
  709. " if (a) {\n"
  710. " if (b) {\n"
  711. " c;\n"
  712. " } else {\n"
  713. " d;\n"
  714. " }\n"
  715. " } else {\n"
  716. " e;\n"
  717. " }\n"
  718. " if (x) { G(1); }\n"
  719. " else if (x) { G(2); }\n"
  720. " else { G(3); }\n"
  721. "}");
  722. ErrorTrackingDiagnosticConsumer error_tracker(consumer);
  723. ParseTree tree = ParseTree::Parse(tokens, error_tracker);
  724. EXPECT_FALSE(tree.HasErrors());
  725. EXPECT_FALSE(error_tracker.SeenError());
  726. EXPECT_THAT(
  727. tree,
  728. MatchParseTreeNodes(
  729. {MatchFunctionWithBody(
  730. MatchIfStatement(
  731. MatchCondition(MatchNameReference("a"), MatchConditionEnd()),
  732. MatchCodeBlock(
  733. MatchIfStatement(
  734. MatchCondition(MatchNameReference("b"),
  735. MatchConditionEnd()),
  736. MatchCodeBlock(MatchExpressionStatement(
  737. MatchNameReference("c")),
  738. MatchCodeBlockEnd()),
  739. MatchIfStatementElse(),
  740. MatchCodeBlock(MatchExpressionStatement(
  741. MatchNameReference("d")),
  742. MatchCodeBlockEnd())),
  743. MatchCodeBlockEnd()),
  744. MatchIfStatementElse(),
  745. MatchCodeBlock(
  746. MatchExpressionStatement(MatchNameReference("e")),
  747. MatchCodeBlockEnd())),
  748. MatchIfStatement(
  749. MatchCondition(MatchNameReference("x"), MatchConditionEnd()),
  750. MatchCodeBlock(
  751. MatchExpressionStatement(MatchCallExpression(
  752. MatchNameReference("G"), MatchLiteral("1"),
  753. MatchCallExpressionEnd())),
  754. MatchCodeBlockEnd()),
  755. MatchIfStatementElse(),
  756. MatchIfStatement(
  757. MatchCondition(MatchNameReference("x"),
  758. MatchConditionEnd()),
  759. MatchCodeBlock(
  760. MatchExpressionStatement(MatchCallExpression(
  761. MatchNameReference("G"), MatchLiteral("2"),
  762. MatchCallExpressionEnd())),
  763. MatchCodeBlockEnd()),
  764. MatchIfStatementElse(),
  765. MatchCodeBlock(
  766. MatchExpressionStatement(MatchCallExpression(
  767. MatchNameReference("G"), MatchLiteral("3"),
  768. MatchCallExpressionEnd())),
  769. MatchCodeBlockEnd())))),
  770. MatchFileEnd()}));
  771. }
  772. TEST_F(ParseTreeTest, IfElseUnbraced) {
  773. TokenizedBuffer tokens = GetTokenizedBuffer(
  774. "fn F() {\n"
  775. " if (a)\n"
  776. " if (b)\n"
  777. " c;\n"
  778. " else\n"
  779. " d;\n"
  780. " else\n"
  781. " e;\n"
  782. " if (x) { G(1); }\n"
  783. " else if (x) { G(2); }\n"
  784. " else { G(3); }\n"
  785. "}");
  786. ErrorTrackingDiagnosticConsumer error_tracker(consumer);
  787. ParseTree tree = ParseTree::Parse(tokens, error_tracker);
  788. // The missing braces are invalid, but we should be able to recover.
  789. EXPECT_FALSE(tree.HasErrors());
  790. EXPECT_TRUE(error_tracker.SeenError());
  791. EXPECT_THAT(
  792. tree,
  793. MatchParseTreeNodes(
  794. {MatchFunctionWithBody(
  795. MatchIfStatement(
  796. MatchCondition(MatchNameReference("a"), MatchConditionEnd()),
  797. MatchIfStatement(
  798. MatchCondition(MatchNameReference("b"),
  799. MatchConditionEnd()),
  800. MatchExpressionStatement(MatchNameReference("c")),
  801. MatchIfStatementElse(),
  802. MatchExpressionStatement(MatchNameReference("d"))),
  803. MatchIfStatementElse(),
  804. MatchExpressionStatement(MatchNameReference("e"))),
  805. MatchIfStatement(
  806. MatchCondition(MatchNameReference("x"), MatchConditionEnd()),
  807. MatchCodeBlock(
  808. MatchExpressionStatement(MatchCallExpression(
  809. MatchNameReference("G"), MatchLiteral("1"),
  810. MatchCallExpressionEnd())),
  811. MatchCodeBlockEnd()),
  812. MatchIfStatementElse(),
  813. MatchIfStatement(
  814. MatchCondition(MatchNameReference("x"),
  815. MatchConditionEnd()),
  816. MatchCodeBlock(
  817. MatchExpressionStatement(MatchCallExpression(
  818. MatchNameReference("G"), MatchLiteral("2"),
  819. MatchCallExpressionEnd())),
  820. MatchCodeBlockEnd()),
  821. MatchIfStatementElse(),
  822. MatchCodeBlock(
  823. MatchExpressionStatement(MatchCallExpression(
  824. MatchNameReference("G"), MatchLiteral("3"),
  825. MatchCallExpressionEnd())),
  826. MatchCodeBlockEnd())))),
  827. MatchFileEnd()}));
  828. }
  829. TEST_F(ParseTreeTest, IfError) {
  830. TokenizedBuffer tokens = GetTokenizedBuffer(
  831. "fn F() {\n"
  832. " if a {}\n"
  833. " if () {}\n"
  834. " if (b c) {}\n"
  835. " if (d)\n"
  836. "}");
  837. ParseTree tree = ParseTree::Parse(tokens, consumer);
  838. EXPECT_TRUE(tree.HasErrors());
  839. EXPECT_THAT(
  840. tree,
  841. MatchParseTreeNodes(
  842. {MatchFunctionWithBody(
  843. MatchIfStatement(HasError, MatchNameReference("a"),
  844. MatchCodeBlock(MatchCodeBlockEnd())),
  845. MatchIfStatement(MatchCondition(HasError, MatchConditionEnd()),
  846. MatchCodeBlock(MatchCodeBlockEnd())),
  847. MatchIfStatement(
  848. MatchCondition(HasError, MatchNameReference("b"),
  849. MatchConditionEnd()),
  850. MatchCodeBlock(MatchCodeBlockEnd())),
  851. MatchIfStatement(HasError,
  852. MatchCondition(MatchNameReference("d"),
  853. MatchConditionEnd()))),
  854. MatchFileEnd()}));
  855. }
  856. TEST_F(ParseTreeTest, WhileBreakContinue) {
  857. TokenizedBuffer tokens = GetTokenizedBuffer(
  858. "fn F() {\n"
  859. " while (a) {\n"
  860. " if (b) {\n"
  861. " break;\n"
  862. " }\n"
  863. " if (c) {\n"
  864. " continue;\n"
  865. " }\n"
  866. "}");
  867. ErrorTrackingDiagnosticConsumer error_tracker(consumer);
  868. ParseTree tree = ParseTree::Parse(tokens, error_tracker);
  869. EXPECT_FALSE(tree.HasErrors());
  870. EXPECT_FALSE(error_tracker.SeenError());
  871. EXPECT_THAT(
  872. tree,
  873. MatchParseTreeNodes(
  874. {MatchFunctionWithBody(MatchWhileStatement(
  875. MatchCondition(MatchNameReference("a"), MatchConditionEnd()),
  876. MatchCodeBlock(
  877. MatchIfStatement(
  878. MatchCondition(MatchNameReference("b"),
  879. MatchConditionEnd()),
  880. MatchCodeBlock(MatchBreakStatement(MatchStatementEnd()),
  881. MatchCodeBlockEnd())),
  882. MatchIfStatement(MatchCondition(MatchNameReference("c"),
  883. MatchConditionEnd()),
  884. MatchCodeBlock(MatchContinueStatement(
  885. MatchStatementEnd()),
  886. MatchCodeBlockEnd())),
  887. MatchCodeBlockEnd()))),
  888. MatchFileEnd()}));
  889. }
  890. TEST_F(ParseTreeTest, WhileUnbraced) {
  891. TokenizedBuffer tokens = GetTokenizedBuffer(
  892. "fn F() {\n"
  893. " while (a) \n"
  894. " break;\n"
  895. "}");
  896. ErrorTrackingDiagnosticConsumer error_tracker(consumer);
  897. ParseTree tree = ParseTree::Parse(tokens, error_tracker);
  898. EXPECT_FALSE(tree.HasErrors());
  899. EXPECT_TRUE(error_tracker.SeenError());
  900. EXPECT_THAT(
  901. tree,
  902. MatchParseTreeNodes(
  903. {MatchFunctionWithBody(MatchWhileStatement(
  904. MatchCondition(MatchNameReference("a"), MatchConditionEnd()),
  905. MatchBreakStatement(MatchStatementEnd()))),
  906. MatchFileEnd()}));
  907. }
  908. TEST_F(ParseTreeTest, Return) {
  909. TokenizedBuffer tokens = GetTokenizedBuffer(
  910. "fn F() {\n"
  911. " if (c) {\n"
  912. " return;\n"
  913. " }\n"
  914. "}\n"
  915. "fn G(x: Foo) -> Foo {\n"
  916. " return x;\n"
  917. "}");
  918. ParseTree tree = ParseTree::Parse(tokens, consumer);
  919. EXPECT_FALSE(tree.HasErrors());
  920. EXPECT_THAT(
  921. tree,
  922. MatchParseTreeNodes(
  923. {MatchFunctionWithBody(MatchIfStatement(
  924. MatchCondition(MatchNameReference("c"), MatchConditionEnd()),
  925. MatchCodeBlock(MatchReturnStatement(MatchStatementEnd()),
  926. MatchCodeBlockEnd()))),
  927. MatchFunctionDeclaration(
  928. MatchDeclaredName(),
  929. MatchParameters(MatchPatternBinding(MatchDeclaredName("x"), ":",
  930. MatchNameReference("Foo"))),
  931. MatchReturnType(MatchNameReference("Foo")),
  932. MatchCodeBlock(MatchReturnStatement(MatchNameReference("x"),
  933. MatchStatementEnd()),
  934. MatchCodeBlockEnd())),
  935. MatchFileEnd()}));
  936. }
  937. TEST_F(ParseTreeTest, Tuples) {
  938. TokenizedBuffer tokens = GetTokenizedBuffer(R"(
  939. var x: (i32, i32) = (1, 2);
  940. var y: ((), (), ());
  941. )");
  942. ParseTree tree = ParseTree::Parse(tokens, consumer);
  943. EXPECT_FALSE(tree.HasErrors());
  944. auto empty_tuple = MatchTupleLiteral(MatchTupleLiteralEnd());
  945. EXPECT_THAT(
  946. tree,
  947. MatchParseTreeNodes(
  948. {MatchVariableDeclaration(
  949. MatchPatternBinding(MatchDeclaredName("x"), ":",
  950. MatchTupleLiteral(MatchLiteral("i32"),
  951. MatchTupleLiteralComma(),
  952. MatchLiteral("i32"),
  953. MatchTupleLiteralEnd())),
  954. MatchVariableInitializer(MatchTupleLiteral(
  955. MatchLiteral("1"), MatchTupleLiteralComma(),
  956. MatchLiteral("2"), MatchTupleLiteralEnd())),
  957. MatchDeclarationEnd()),
  958. MatchVariableDeclaration(
  959. MatchPatternBinding(
  960. MatchDeclaredName("y"), ":",
  961. MatchTupleLiteral(empty_tuple, MatchTupleLiteralComma(),
  962. empty_tuple, MatchTupleLiteralComma(),
  963. empty_tuple, MatchTupleLiteralEnd())),
  964. MatchDeclarationEnd()),
  965. MatchFileEnd()}));
  966. }
  967. TEST_F(ParseTreeTest, Structs) {
  968. TokenizedBuffer tokens = GetTokenizedBuffer(R"(
  969. var x: {.a: i32, .b: i32} = {.a = 1, .b = 2};
  970. var y: {} = {};
  971. var z: {.n: i32,} = {.n = 4,};
  972. )");
  973. ParseTree tree = ParseTree::Parse(tokens, consumer);
  974. EXPECT_FALSE(tree.HasErrors());
  975. EXPECT_THAT(
  976. tree,
  977. MatchParseTreeNodes(
  978. {MatchVariableDeclaration(
  979. MatchPatternBinding(
  980. MatchDeclaredName("x"), ":",
  981. MatchStructTypeLiteral(
  982. MatchStructFieldType(MatchStructFieldDesignator(
  983. ".", MatchDesignatedName("a")),
  984. ":", MatchLiteral("i32")),
  985. MatchStructComma(),
  986. MatchStructFieldType(MatchStructFieldDesignator(
  987. ".", MatchDesignatedName("b")),
  988. ":", MatchLiteral("i32")),
  989. MatchStructEnd())),
  990. MatchVariableInitializer(MatchStructLiteral(
  991. MatchStructFieldValue(MatchStructFieldDesignator(
  992. ".", MatchDesignatedName("a")),
  993. "=", MatchLiteral("1")),
  994. MatchStructComma(),
  995. MatchStructFieldValue(MatchStructFieldDesignator(
  996. ".", MatchDesignatedName("b")),
  997. "=", MatchLiteral("2")),
  998. MatchStructEnd())),
  999. MatchDeclarationEnd()),
  1000. MatchVariableDeclaration(
  1001. MatchPatternBinding(MatchDeclaredName("y"), ":",
  1002. MatchStructLiteral(MatchStructEnd())),
  1003. MatchVariableInitializer(MatchStructLiteral(MatchStructEnd())),
  1004. MatchDeclarationEnd()),
  1005. MatchVariableDeclaration(
  1006. MatchPatternBinding(
  1007. MatchDeclaredName("z"), ":",
  1008. MatchStructTypeLiteral(
  1009. MatchStructFieldType(MatchStructFieldDesignator(
  1010. ".", MatchDesignatedName("n")),
  1011. ":", MatchLiteral("i32")),
  1012. MatchStructComma(), MatchStructEnd())),
  1013. MatchVariableInitializer(MatchStructLiteral(
  1014. MatchStructFieldValue(MatchStructFieldDesignator(
  1015. ".", MatchDesignatedName("n")),
  1016. "=", MatchLiteral("4")),
  1017. MatchStructComma(), MatchStructEnd())),
  1018. MatchDeclarationEnd()),
  1019. MatchFileEnd()}));
  1020. }
  1021. TEST_F(ParseTreeTest, StructErrors) {
  1022. struct Testcase {
  1023. llvm::StringLiteral input;
  1024. ::testing::Matcher<const Diagnostic&> diag_matcher;
  1025. };
  1026. Testcase testcases[] = {
  1027. {"var x: {i32} = {};",
  1028. DiagnosticMessage("Expected `.field: type` or `.field = value`.")},
  1029. {"var x: {a} = {};",
  1030. DiagnosticMessage("Expected `.field: type` or `.field = value`.")},
  1031. {"var x: {a:} = {};",
  1032. DiagnosticMessage("Expected `.field: type` or `.field = value`.")},
  1033. {"var x: {a=} = {};",
  1034. DiagnosticMessage("Expected `.field: type` or `.field = value`.")},
  1035. {"var x: {.} = {};", DiagnosticMessage("Expected identifier after `.`.")},
  1036. {"var x: {.\"hello\" = 0, .y = 4} = {};",
  1037. DiagnosticMessage("Expected identifier after `.`.")},
  1038. {"var x: {.\"hello\": i32, .y: i32} = {};",
  1039. DiagnosticMessage("Expected identifier after `.`.")},
  1040. {"var x: {.a} = {};",
  1041. DiagnosticMessage("Expected `.field: type` or `.field = value`.")},
  1042. {"var x: {.a:} = {};", DiagnosticMessage("Expected expression.")},
  1043. {"var x: {.a=} = {};", DiagnosticMessage("Expected expression.")},
  1044. {"var x: {.a: i32, .b = 0} = {};",
  1045. DiagnosticMessage("Expected `.field: type`.")},
  1046. {"var x: {.a = 0, b: i32} = {};",
  1047. DiagnosticMessage("Expected `.field = value`.")},
  1048. {"var x: {,} = {};",
  1049. DiagnosticMessage("Expected `.field: type` or `.field = value`.")},
  1050. {"var x: {.a: i32,,} = {};",
  1051. DiagnosticMessage("Expected `.field: type`.")},
  1052. {"var x: {.a = 0,,} = {};",
  1053. DiagnosticMessage("Expected `.field = value`.")},
  1054. {"var x: {.a: i32 banana} = {.a = 0};",
  1055. DiagnosticMessage("Expected `,` or `}`.")},
  1056. {"var x: {.a: i32} = {.a = 0 banana};",
  1057. DiagnosticMessage("Expected `,` or `}`.")},
  1058. };
  1059. for (const Testcase& testcase : testcases) {
  1060. TokenizedBuffer tokens = GetTokenizedBuffer(testcase.input);
  1061. Testing::MockDiagnosticConsumer consumer;
  1062. EXPECT_CALL(consumer, HandleDiagnostic(testcase.diag_matcher));
  1063. ParseTree tree = ParseTree::Parse(tokens, consumer);
  1064. EXPECT_TRUE(tree.HasErrors());
  1065. }
  1066. }
  1067. auto GetAndDropLine(llvm::StringRef& s) -> std::string {
  1068. auto newline_offset = s.find_first_of('\n');
  1069. llvm::StringRef line = s.slice(0, newline_offset);
  1070. if (newline_offset != llvm::StringRef::npos) {
  1071. s = s.substr(newline_offset + 1);
  1072. } else {
  1073. s = "";
  1074. }
  1075. return line.str();
  1076. }
  1077. TEST_F(ParseTreeTest, Printing) {
  1078. TokenizedBuffer tokens = GetTokenizedBuffer("fn F();");
  1079. ParseTree tree = ParseTree::Parse(tokens, consumer);
  1080. EXPECT_FALSE(tree.HasErrors());
  1081. std::string print_storage;
  1082. llvm::raw_string_ostream print_stream(print_storage);
  1083. tree.Print(print_stream);
  1084. llvm::StringRef print = print_stream.str();
  1085. EXPECT_THAT(GetAndDropLine(print), StrEq("["));
  1086. EXPECT_THAT(GetAndDropLine(print),
  1087. StrEq("{node_index: 4, kind: 'FunctionDeclaration', text: 'fn', "
  1088. "subtree_size: 5, children: ["));
  1089. EXPECT_THAT(GetAndDropLine(print),
  1090. StrEq(" {node_index: 0, kind: 'DeclaredName', text: 'F'},"));
  1091. EXPECT_THAT(GetAndDropLine(print),
  1092. StrEq(" {node_index: 2, kind: 'ParameterList', text: '(', "
  1093. "subtree_size: 2, children: ["));
  1094. EXPECT_THAT(GetAndDropLine(print),
  1095. StrEq(" {node_index: 1, kind: 'ParameterListEnd', "
  1096. "text: ')'}]},"));
  1097. EXPECT_THAT(GetAndDropLine(print),
  1098. StrEq(" {node_index: 3, kind: 'DeclarationEnd', text: ';'}]},"));
  1099. EXPECT_THAT(GetAndDropLine(print),
  1100. StrEq("{node_index: 5, kind: 'FileEnd', text: ''},"));
  1101. EXPECT_THAT(GetAndDropLine(print), StrEq("]"));
  1102. EXPECT_TRUE(print.empty()) << print;
  1103. }
  1104. TEST_F(ParseTreeTest, PrintingAsYAML) {
  1105. TokenizedBuffer tokens = GetTokenizedBuffer("fn F();");
  1106. ParseTree tree = ParseTree::Parse(tokens, consumer);
  1107. EXPECT_FALSE(tree.HasErrors());
  1108. std::string print_output;
  1109. llvm::raw_string_ostream print_stream(print_output);
  1110. tree.Print(print_stream);
  1111. print_stream.flush();
  1112. EXPECT_THAT(
  1113. Yaml::Value::FromText(print_output),
  1114. ElementsAre(Yaml::SequenceValue{
  1115. Yaml::MappingValue{
  1116. {"node_index", "4"},
  1117. {"kind", "FunctionDeclaration"},
  1118. {"text", "fn"},
  1119. {"subtree_size", "5"},
  1120. {"children",
  1121. Yaml::SequenceValue{
  1122. Yaml::MappingValue{{"node_index", "0"},
  1123. {"kind", "DeclaredName"},
  1124. {"text", "F"}},
  1125. Yaml::MappingValue{{"node_index", "2"},
  1126. {"kind", "ParameterList"},
  1127. {"text", "("},
  1128. {"subtree_size", "2"},
  1129. {"children", //
  1130. Yaml::SequenceValue{Yaml::MappingValue{
  1131. {"node_index", "1"},
  1132. {"kind", "ParameterListEnd"},
  1133. {"text", ")"}}}}},
  1134. Yaml::MappingValue{{"node_index", "3"},
  1135. {"kind", "DeclarationEnd"},
  1136. {"text", ";"}}}}},
  1137. Yaml::MappingValue{{"node_index", "5"}, //
  1138. {"kind", "FileEnd"},
  1139. {"text", ""}}}));
  1140. }
  1141. TEST_F(ParseTreeTest, ParenMatchRegression) {
  1142. // A regression test that the search for the closing `)` doesn't end early on
  1143. // the closing `}` when it skips over the nested scope.
  1144. TokenizedBuffer tokens = GetTokenizedBuffer("var = (foo {})");
  1145. ParseTree tree = ParseTree::Parse(tokens, consumer);
  1146. EXPECT_TRUE(tree.HasErrors());
  1147. EXPECT_THAT(
  1148. tree, MatchParseTreeNodes(
  1149. {MatchVariableDeclaration(
  1150. HasError, MatchVariableInitializer(
  1151. "=", MatchParenExpression(
  1152. HasError, MatchNameReference("foo"),
  1153. MatchParenExpressionEnd()))),
  1154. MatchFileEnd()}));
  1155. }
  1156. TEST_F(ParseTreeTest, RecursionLimit) {
  1157. std::string code = "fn Foo() { return ";
  1158. code.append(10000, '(');
  1159. code.append(10000, ')');
  1160. code += "; }";
  1161. TokenizedBuffer tokens = GetTokenizedBuffer(code);
  1162. ASSERT_FALSE(tokens.has_errors());
  1163. Testing::MockDiagnosticConsumer consumer;
  1164. // Recursion might be exceeded multiple times due to quirks in parse tree
  1165. // handling; we only need to be sure it's hit at least once for test
  1166. // correctness.
  1167. EXPECT_CALL(
  1168. consumer,
  1169. HandleDiagnostic(DiagnosticMessage(llvm::formatv(
  1170. "Exceeded recursion limit ({0})", ParseTree::StackDepthLimit))))
  1171. .Times(AtLeast(1));
  1172. ParseTree tree = ParseTree::Parse(tokens, consumer);
  1173. EXPECT_TRUE(tree.HasErrors());
  1174. }
  1175. TEST_F(ParseTreeTest, ParsePostfixExpressionRegression) {
  1176. // Stack depth errors could cause ParsePostfixExpression to infinitely loop
  1177. // when calling children and those children error. Because of the fragility of
  1178. // stack depth, this tries a few different values.
  1179. for (int n = 0; n <= 10; ++n) {
  1180. std::string code = "var x: auto = ";
  1181. code.append(ParseTree::StackDepthLimit - n, '*');
  1182. code += "(z);";
  1183. TokenizedBuffer tokens = GetTokenizedBuffer(code);
  1184. ASSERT_FALSE(tokens.has_errors());
  1185. ParseTree tree = ParseTree::Parse(tokens, consumer);
  1186. EXPECT_TRUE(tree.HasErrors());
  1187. }
  1188. }
  1189. } // namespace
  1190. } // namespace Carbon::Testing