parse_tree_test.cpp 48 KB

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