parse_tree_test.cpp 51 KB

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