parse_tree_test.cpp 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054
  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 <forward_list>
  6. #include "gmock/gmock.h"
  7. #include "gtest/gtest.h"
  8. #include "llvm/ADT/Sequence.h"
  9. #include "llvm/Support/SourceMgr.h"
  10. #include "toolchain/common/yaml_test_helpers.h"
  11. #include "toolchain/diagnostics/diagnostic_emitter.h"
  12. #include "toolchain/lexer/tokenized_buffer.h"
  13. #include "toolchain/parser/parse_node_kind.h"
  14. #include "toolchain/parser/parse_test_helpers.h"
  15. namespace Carbon {
  16. namespace {
  17. using Carbon::Testing::ExpectedNode;
  18. using Carbon::Testing::MatchParseTreeNodes;
  19. using namespace Carbon::Testing::NodeMatchers;
  20. using ::testing::ElementsAre;
  21. using ::testing::Eq;
  22. using ::testing::Ne;
  23. using ::testing::NotNull;
  24. using ::testing::StrEq;
  25. namespace Yaml = Carbon::Testing::Yaml;
  26. struct ParseTreeTest : ::testing::Test {
  27. std::forward_list<SourceBuffer> source_storage;
  28. std::forward_list<TokenizedBuffer> token_storage;
  29. DiagnosticConsumer& consumer = ConsoleDiagnosticConsumer();
  30. auto GetSourceBuffer(llvm::Twine t) -> SourceBuffer& {
  31. source_storage.push_front(SourceBuffer::CreateFromText(t.str()));
  32. return source_storage.front();
  33. }
  34. auto GetTokenizedBuffer(llvm::Twine t) -> TokenizedBuffer& {
  35. token_storage.push_front(
  36. TokenizedBuffer::Lex(GetSourceBuffer(t), consumer));
  37. return token_storage.front();
  38. }
  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. ";"),
  369. MatchExpressionStatement(
  370. MatchDesignatorExpression(
  371. MatchNameReference("a"), ".", HasError),
  372. ";"),
  373. MatchExpressionStatement(
  374. MatchDesignatorExpression(
  375. MatchNameReference("a"), ".", HasError),
  376. HasError, ";")),
  377. MatchFileEnd()}));
  378. }
  379. TEST_F(ParseTreeTest, Operators) {
  380. TokenizedBuffer tokens = GetTokenizedBuffer(
  381. "fn F() {\n"
  382. " n = a * b + c * d = d * d << e & f - not g;\n"
  383. " ++++n;\n"
  384. " n++++;\n"
  385. " a and b and c;\n"
  386. " a and b or c;\n"
  387. " a or b and c;\n"
  388. " not a and not b and not c;\n"
  389. "}");
  390. ParseTree tree = ParseTree::Parse(tokens, consumer);
  391. EXPECT_TRUE(tree.HasErrors());
  392. EXPECT_THAT(
  393. tree,
  394. MatchParseTreeNodes(
  395. {MatchFunctionWithBody(
  396. MatchExpressionStatement(MatchInfixOperator(
  397. MatchNameReference("n"), "=",
  398. MatchInfixOperator(
  399. MatchInfixOperator(
  400. MatchInfixOperator(MatchNameReference("a"), "*",
  401. MatchNameReference("b")),
  402. "+",
  403. MatchInfixOperator(MatchNameReference("c"), "*",
  404. MatchNameReference("d"))),
  405. "=",
  406. MatchInfixOperator(
  407. HasError,
  408. MatchInfixOperator(
  409. HasError,
  410. MatchInfixOperator(
  411. HasError,
  412. MatchInfixOperator(MatchNameReference("d"),
  413. "*",
  414. MatchNameReference("d")),
  415. "<<", MatchNameReference("e")),
  416. "&", MatchNameReference("f")),
  417. "-",
  418. MatchPrefixOperator("not",
  419. MatchNameReference("g")))))),
  420. MatchExpressionStatement(MatchPrefixOperator(
  421. "++", MatchPrefixOperator("++", MatchNameReference("n")))),
  422. MatchExpressionStatement(MatchPostfixOperator(
  423. MatchPostfixOperator(MatchNameReference("n"), "++"), "++")),
  424. MatchExpressionStatement(MatchInfixOperator(
  425. MatchInfixOperator(MatchNameReference("a"), "and",
  426. MatchNameReference("b")),
  427. "and", MatchNameReference("c"))),
  428. MatchExpressionStatement(MatchInfixOperator(
  429. HasError,
  430. MatchInfixOperator(MatchNameReference("a"), "and",
  431. MatchNameReference("b")),
  432. "or", MatchNameReference("c"))),
  433. MatchExpressionStatement(MatchInfixOperator(
  434. HasError,
  435. MatchInfixOperator(MatchNameReference("a"), "or",
  436. MatchNameReference("b")),
  437. "and", MatchNameReference("c"))),
  438. MatchExpressionStatement(MatchInfixOperator(
  439. MatchInfixOperator(
  440. MatchPrefixOperator("not", MatchNameReference("a")),
  441. "and",
  442. MatchPrefixOperator("not", MatchNameReference("b"))),
  443. "and",
  444. MatchPrefixOperator("not", MatchNameReference("c"))))),
  445. MatchFileEnd()}));
  446. }
  447. TEST_F(ParseTreeTest, OperatorFixity) {
  448. TokenizedBuffer tokens = GetTokenizedBuffer(
  449. "fn F(p: i32*, n: i32) {\n"
  450. " var q: i32* = p;\n"
  451. " var t: Type = i32*;\n"
  452. " t = t**;\n"
  453. " n = n * n;\n"
  454. " n = n * *p;\n"
  455. " n = n*n;\n"
  456. " G(i32*, n * n);\n"
  457. "}");
  458. ParseTree tree = ParseTree::Parse(tokens, consumer);
  459. EXPECT_FALSE(tree.HasErrors());
  460. EXPECT_THAT(
  461. tree,
  462. MatchParseTreeNodes(
  463. {MatchFunctionDeclaration(
  464. MatchDeclaredName("F"),
  465. MatchParameters(
  466. MatchPatternBinding(
  467. MatchDeclaredName("p"),
  468. MatchPostfixOperator(MatchLiteral("i32"), "*")),
  469. MatchParameterListComma(),
  470. MatchPatternBinding(MatchDeclaredName("n"),
  471. MatchLiteral("i32"))),
  472. MatchCodeBlock(
  473. MatchVariableDeclaration(
  474. MatchPatternBinding(
  475. MatchDeclaredName("q"),
  476. MatchPostfixOperator(MatchLiteral("i32"), "*")),
  477. MatchVariableInitializer(MatchNameReference("p")),
  478. MatchDeclarationEnd()),
  479. MatchVariableDeclaration(
  480. MatchPatternBinding(MatchDeclaredName("t"),
  481. MatchNameReference("Type")),
  482. MatchVariableInitializer(
  483. MatchPostfixOperator(MatchLiteral("i32"), "*")),
  484. MatchDeclarationEnd()),
  485. MatchExpressionStatement(MatchInfixOperator(
  486. MatchNameReference("t"), "=",
  487. MatchPostfixOperator(
  488. MatchPostfixOperator(MatchNameReference("t"), "*"),
  489. "*"))),
  490. MatchExpressionStatement(MatchInfixOperator(
  491. MatchNameReference("n"), "=",
  492. MatchInfixOperator(MatchNameReference("n"), "*",
  493. MatchNameReference("n")))),
  494. MatchExpressionStatement(MatchInfixOperator(
  495. MatchNameReference("n"), "=",
  496. MatchInfixOperator(
  497. MatchNameReference("n"), "*",
  498. MatchPrefixOperator("*", MatchNameReference("p"))))),
  499. MatchExpressionStatement(MatchInfixOperator(
  500. MatchNameReference("n"), "=",
  501. MatchInfixOperator(MatchNameReference("n"), "*",
  502. MatchNameReference("n")))),
  503. MatchExpressionStatement(MatchCallExpression(
  504. MatchNameReference("G"),
  505. MatchPostfixOperator(MatchLiteral("i32"), "*"),
  506. MatchCallExpressionComma(),
  507. MatchInfixOperator(MatchNameReference("n"), "*",
  508. MatchNameReference("n")),
  509. MatchCallExpressionEnd())),
  510. MatchCodeBlockEnd())),
  511. MatchFileEnd()}));
  512. }
  513. TEST_F(ParseTreeTest, OperatorWhitespaceErrors) {
  514. // Test dispositions: Recovered means we issued an error but recovered a
  515. // proper parse tree; Failed means we didn't fully recover from the error.
  516. enum Kind { Valid, Recovered, Failed };
  517. struct Testcase {
  518. const char* input;
  519. Kind kind;
  520. } testcases[] = {
  521. {"var v: Type = i8*;", Valid},
  522. {"var v: Type = i8 *;", Recovered},
  523. {"var v: Type = i8* ;", Valid},
  524. {"var v: Type = i8 * ;", Recovered},
  525. {"var n: i8 = n * n;", Valid},
  526. {"var n: i8 = n*n;", Valid},
  527. {"var n: i8 = (n)*3;", Valid},
  528. {"var n: i8 = 3*(n);", Valid},
  529. {"var n: i8 = n *n;", Recovered},
  530. // FIXME: We could figure out that this first Failed example is infix
  531. // with one-token lookahead.
  532. {"var n: i8 = n* n;", Failed},
  533. {"var n: i8 = n* -n;", Failed},
  534. {"var n: i8 = n* *p;", Failed},
  535. // FIXME: We try to form (n*)*p and reject due to missing parentheses
  536. // before we notice the missing whitespace around the second `*`.
  537. // It'd be better to (somehow) form n*(*p) and reject due to the missing
  538. // whitespace around the first `*`.
  539. {"var n: i8 = n**p;", Failed},
  540. {"var n: i8 = -n;", Valid},
  541. {"var n: i8 = - n;", Recovered},
  542. {"var n: i8 =-n;", Valid},
  543. {"var n: i8 =- n;", Recovered},
  544. {"var n: i8 = F(i8 *);", Recovered},
  545. {"var n: i8 = F(i8 *, 0);", Recovered},
  546. };
  547. for (auto [input, kind] : testcases) {
  548. TokenizedBuffer tokens = GetTokenizedBuffer(input);
  549. ErrorTrackingDiagnosticConsumer error_tracker(consumer);
  550. ParseTree tree = ParseTree::Parse(tokens, error_tracker);
  551. EXPECT_THAT(tree.HasErrors(), Eq(kind == Failed)) << input;
  552. EXPECT_THAT(error_tracker.SeenError(), Eq(kind != Valid)) << input;
  553. }
  554. }
  555. TEST_F(ParseTreeTest, VariableDeclarations) {
  556. TokenizedBuffer tokens = GetTokenizedBuffer(
  557. "var v: i32 = 0;\n"
  558. "var w: i32;\n"
  559. "fn F() {\n"
  560. " var s: String = \"hello\";\n"
  561. "}");
  562. ParseTree tree = ParseTree::Parse(tokens, consumer);
  563. EXPECT_FALSE(tree.HasErrors());
  564. EXPECT_THAT(tree,
  565. MatchParseTreeNodes(
  566. {MatchVariableDeclaration(
  567. MatchPatternBinding(MatchDeclaredName("v"), ":",
  568. MatchLiteral("i32")),
  569. MatchVariableInitializer(MatchLiteral("0")),
  570. MatchDeclarationEnd()),
  571. MatchVariableDeclaration(
  572. MatchPatternBinding(MatchDeclaredName("w"), ":",
  573. MatchLiteral("i32")),
  574. MatchDeclarationEnd()),
  575. MatchFunctionWithBody(MatchVariableDeclaration(
  576. MatchPatternBinding(MatchDeclaredName("s"), ":",
  577. MatchNameReference("String")),
  578. MatchVariableInitializer(MatchLiteral("\"hello\"")),
  579. MatchDeclarationEnd())),
  580. MatchFileEnd()}));
  581. }
  582. TEST_F(ParseTreeTest, IfNoElse) {
  583. TokenizedBuffer tokens = GetTokenizedBuffer(
  584. "fn F() {\n"
  585. " if (a) {\n"
  586. " if (b) {\n"
  587. " if (c) {\n"
  588. " d;\n"
  589. " }\n"
  590. " }\n"
  591. " }\n"
  592. "}");
  593. ErrorTrackingDiagnosticConsumer error_tracker(consumer);
  594. ParseTree tree = ParseTree::Parse(tokens, error_tracker);
  595. EXPECT_FALSE(tree.HasErrors());
  596. EXPECT_FALSE(error_tracker.SeenError());
  597. EXPECT_THAT(
  598. tree,
  599. MatchParseTreeNodes(
  600. {MatchFunctionWithBody(MatchIfStatement(
  601. MatchCondition(MatchNameReference("a"), MatchConditionEnd()),
  602. MatchCodeBlock(
  603. MatchIfStatement(
  604. MatchCondition(MatchNameReference("b"),
  605. MatchConditionEnd()),
  606. MatchCodeBlock(
  607. MatchIfStatement(
  608. MatchCondition(MatchNameReference("c"),
  609. MatchConditionEnd()),
  610. MatchCodeBlock(MatchExpressionStatement(
  611. MatchNameReference("d")),
  612. MatchCodeBlockEnd())),
  613. MatchCodeBlockEnd())),
  614. MatchCodeBlockEnd()))),
  615. MatchFileEnd()}));
  616. }
  617. TEST_F(ParseTreeTest, IfNoElseUnbraced) {
  618. TokenizedBuffer tokens = GetTokenizedBuffer(
  619. "fn F() {\n"
  620. " if (a)\n"
  621. " if (b)\n"
  622. " if (c)\n"
  623. " d;\n"
  624. "}");
  625. ErrorTrackingDiagnosticConsumer error_tracker(consumer);
  626. ParseTree tree = ParseTree::Parse(tokens, error_tracker);
  627. // The missing braces are invalid, but we should be able to recover.
  628. EXPECT_FALSE(tree.HasErrors());
  629. EXPECT_TRUE(error_tracker.SeenError());
  630. EXPECT_THAT(
  631. tree,
  632. MatchParseTreeNodes(
  633. {MatchFunctionWithBody(MatchIfStatement(
  634. MatchCondition(MatchNameReference("a"), MatchConditionEnd()),
  635. MatchIfStatement(
  636. MatchCondition(MatchNameReference("b"), MatchConditionEnd()),
  637. MatchIfStatement(
  638. MatchCondition(MatchNameReference("c"),
  639. MatchConditionEnd()),
  640. MatchExpressionStatement(MatchNameReference("d")))))),
  641. MatchFileEnd()}));
  642. }
  643. TEST_F(ParseTreeTest, IfElse) {
  644. TokenizedBuffer tokens = GetTokenizedBuffer(
  645. "fn F() {\n"
  646. " if (a) {\n"
  647. " if (b) {\n"
  648. " c;\n"
  649. " } else {\n"
  650. " d;\n"
  651. " }\n"
  652. " } else {\n"
  653. " e;\n"
  654. " }\n"
  655. " if (x) { G(1); }\n"
  656. " else if (x) { G(2); }\n"
  657. " else { G(3); }\n"
  658. "}");
  659. ErrorTrackingDiagnosticConsumer error_tracker(consumer);
  660. ParseTree tree = ParseTree::Parse(tokens, error_tracker);
  661. EXPECT_FALSE(tree.HasErrors());
  662. EXPECT_FALSE(error_tracker.SeenError());
  663. EXPECT_THAT(
  664. tree,
  665. MatchParseTreeNodes(
  666. {MatchFunctionWithBody(
  667. MatchIfStatement(
  668. MatchCondition(MatchNameReference("a"), MatchConditionEnd()),
  669. MatchCodeBlock(
  670. MatchIfStatement(
  671. MatchCondition(MatchNameReference("b"),
  672. MatchConditionEnd()),
  673. MatchCodeBlock(MatchExpressionStatement(
  674. MatchNameReference("c")),
  675. MatchCodeBlockEnd()),
  676. MatchIfStatementElse(),
  677. MatchCodeBlock(MatchExpressionStatement(
  678. MatchNameReference("d")),
  679. MatchCodeBlockEnd())),
  680. MatchCodeBlockEnd()),
  681. MatchIfStatementElse(),
  682. MatchCodeBlock(
  683. MatchExpressionStatement(MatchNameReference("e")),
  684. MatchCodeBlockEnd())),
  685. MatchIfStatement(
  686. MatchCondition(MatchNameReference("x"), MatchConditionEnd()),
  687. MatchCodeBlock(
  688. MatchExpressionStatement(MatchCallExpression(
  689. MatchNameReference("G"), MatchLiteral("1"),
  690. MatchCallExpressionEnd())),
  691. MatchCodeBlockEnd()),
  692. MatchIfStatementElse(),
  693. MatchIfStatement(
  694. MatchCondition(MatchNameReference("x"),
  695. MatchConditionEnd()),
  696. MatchCodeBlock(
  697. MatchExpressionStatement(MatchCallExpression(
  698. MatchNameReference("G"), MatchLiteral("2"),
  699. MatchCallExpressionEnd())),
  700. MatchCodeBlockEnd()),
  701. MatchIfStatementElse(),
  702. MatchCodeBlock(
  703. MatchExpressionStatement(MatchCallExpression(
  704. MatchNameReference("G"), MatchLiteral("3"),
  705. MatchCallExpressionEnd())),
  706. MatchCodeBlockEnd())))),
  707. MatchFileEnd()}));
  708. }
  709. TEST_F(ParseTreeTest, IfElseUnbraced) {
  710. TokenizedBuffer tokens = GetTokenizedBuffer(
  711. "fn F() {\n"
  712. " if (a)\n"
  713. " if (b)\n"
  714. " c;\n"
  715. " else\n"
  716. " d;\n"
  717. " else\n"
  718. " e;\n"
  719. " if (x) { G(1); }\n"
  720. " else if (x) { G(2); }\n"
  721. " else { G(3); }\n"
  722. "}");
  723. ErrorTrackingDiagnosticConsumer error_tracker(consumer);
  724. ParseTree tree = ParseTree::Parse(tokens, error_tracker);
  725. // The missing braces are invalid, but we should be able to recover.
  726. EXPECT_FALSE(tree.HasErrors());
  727. EXPECT_TRUE(error_tracker.SeenError());
  728. EXPECT_THAT(
  729. tree,
  730. MatchParseTreeNodes(
  731. {MatchFunctionWithBody(
  732. MatchIfStatement(
  733. MatchCondition(MatchNameReference("a"), MatchConditionEnd()),
  734. MatchIfStatement(
  735. MatchCondition(MatchNameReference("b"),
  736. MatchConditionEnd()),
  737. MatchExpressionStatement(MatchNameReference("c")),
  738. MatchIfStatementElse(),
  739. MatchExpressionStatement(MatchNameReference("d"))),
  740. MatchIfStatementElse(),
  741. MatchExpressionStatement(MatchNameReference("e"))),
  742. MatchIfStatement(
  743. MatchCondition(MatchNameReference("x"), MatchConditionEnd()),
  744. MatchCodeBlock(
  745. MatchExpressionStatement(MatchCallExpression(
  746. MatchNameReference("G"), MatchLiteral("1"),
  747. MatchCallExpressionEnd())),
  748. MatchCodeBlockEnd()),
  749. MatchIfStatementElse(),
  750. MatchIfStatement(
  751. MatchCondition(MatchNameReference("x"),
  752. MatchConditionEnd()),
  753. MatchCodeBlock(
  754. MatchExpressionStatement(MatchCallExpression(
  755. MatchNameReference("G"), MatchLiteral("2"),
  756. MatchCallExpressionEnd())),
  757. MatchCodeBlockEnd()),
  758. MatchIfStatementElse(),
  759. MatchCodeBlock(
  760. MatchExpressionStatement(MatchCallExpression(
  761. MatchNameReference("G"), MatchLiteral("3"),
  762. MatchCallExpressionEnd())),
  763. MatchCodeBlockEnd())))),
  764. MatchFileEnd()}));
  765. }
  766. TEST_F(ParseTreeTest, IfError) {
  767. TokenizedBuffer tokens = GetTokenizedBuffer(
  768. "fn F() {\n"
  769. " if a {}\n"
  770. " if () {}\n"
  771. " if (b c) {}\n"
  772. " if (d)\n"
  773. "}");
  774. ParseTree tree = ParseTree::Parse(tokens, consumer);
  775. EXPECT_TRUE(tree.HasErrors());
  776. EXPECT_THAT(
  777. tree,
  778. MatchParseTreeNodes(
  779. {MatchFunctionWithBody(
  780. MatchIfStatement(HasError, MatchNameReference("a"),
  781. MatchCodeBlock(MatchCodeBlockEnd())),
  782. MatchIfStatement(MatchCondition(HasError, MatchConditionEnd()),
  783. MatchCodeBlock(MatchCodeBlockEnd())),
  784. MatchIfStatement(
  785. MatchCondition(HasError, MatchNameReference("b"),
  786. MatchConditionEnd()),
  787. MatchCodeBlock(MatchCodeBlockEnd())),
  788. MatchIfStatement(HasError,
  789. MatchCondition(MatchNameReference("d"),
  790. MatchConditionEnd()))),
  791. MatchFileEnd()}));
  792. }
  793. TEST_F(ParseTreeTest, WhileBreakContinue) {
  794. TokenizedBuffer tokens = GetTokenizedBuffer(
  795. "fn F() {\n"
  796. " while (a) {\n"
  797. " if (b) {\n"
  798. " break;\n"
  799. " }\n"
  800. " if (c) {\n"
  801. " continue;\n"
  802. " }\n"
  803. "}");
  804. ErrorTrackingDiagnosticConsumer error_tracker(consumer);
  805. ParseTree tree = ParseTree::Parse(tokens, error_tracker);
  806. EXPECT_FALSE(tree.HasErrors());
  807. EXPECT_FALSE(error_tracker.SeenError());
  808. EXPECT_THAT(
  809. tree,
  810. MatchParseTreeNodes(
  811. {MatchFunctionWithBody(MatchWhileStatement(
  812. MatchCondition(MatchNameReference("a"), MatchConditionEnd()),
  813. MatchCodeBlock(
  814. MatchIfStatement(
  815. MatchCondition(MatchNameReference("b"),
  816. MatchConditionEnd()),
  817. MatchCodeBlock(MatchBreakStatement(MatchStatementEnd()),
  818. MatchCodeBlockEnd())),
  819. MatchIfStatement(MatchCondition(MatchNameReference("c"),
  820. MatchConditionEnd()),
  821. MatchCodeBlock(MatchContinueStatement(
  822. MatchStatementEnd()),
  823. MatchCodeBlockEnd())),
  824. MatchCodeBlockEnd()))),
  825. MatchFileEnd()}));
  826. }
  827. TEST_F(ParseTreeTest, WhileUnbraced) {
  828. TokenizedBuffer tokens = GetTokenizedBuffer(
  829. "fn F() {\n"
  830. " while (a) \n"
  831. " break;\n"
  832. "}");
  833. ErrorTrackingDiagnosticConsumer error_tracker(consumer);
  834. ParseTree tree = ParseTree::Parse(tokens, error_tracker);
  835. EXPECT_FALSE(tree.HasErrors());
  836. EXPECT_TRUE(error_tracker.SeenError());
  837. EXPECT_THAT(
  838. tree,
  839. MatchParseTreeNodes(
  840. {MatchFunctionWithBody(MatchWhileStatement(
  841. MatchCondition(MatchNameReference("a"), MatchConditionEnd()),
  842. MatchBreakStatement(MatchStatementEnd()))),
  843. MatchFileEnd()}));
  844. }
  845. TEST_F(ParseTreeTest, Return) {
  846. TokenizedBuffer tokens = GetTokenizedBuffer(
  847. "fn F() {\n"
  848. " if (c) {\n"
  849. " return;\n"
  850. " }\n"
  851. "}\n"
  852. "fn G(x: Foo) -> Foo {\n"
  853. " return x;\n"
  854. "}");
  855. ParseTree tree = ParseTree::Parse(tokens, consumer);
  856. EXPECT_FALSE(tree.HasErrors());
  857. EXPECT_THAT(
  858. tree,
  859. MatchParseTreeNodes(
  860. {MatchFunctionWithBody(MatchIfStatement(
  861. MatchCondition(MatchNameReference("c"), MatchConditionEnd()),
  862. MatchCodeBlock(MatchReturnStatement(MatchStatementEnd()),
  863. MatchCodeBlockEnd()))),
  864. MatchFunctionDeclaration(
  865. MatchDeclaredName(),
  866. MatchParameters(MatchPatternBinding(MatchDeclaredName("x"), ":",
  867. MatchNameReference("Foo"))),
  868. MatchReturnType(MatchNameReference("Foo")),
  869. MatchCodeBlock(MatchReturnStatement(MatchNameReference("x"),
  870. MatchStatementEnd()),
  871. MatchCodeBlockEnd())),
  872. MatchFileEnd()}));
  873. }
  874. TEST_F(ParseTreeTest, Tuples) {
  875. TokenizedBuffer tokens = GetTokenizedBuffer(R"(
  876. var x: (i32, i32) = (1, 2);
  877. var y: ((), (), ());
  878. )");
  879. ParseTree tree = ParseTree::Parse(tokens, consumer);
  880. EXPECT_FALSE(tree.HasErrors());
  881. auto empty_tuple = MatchTupleLiteral(MatchTupleLiteralEnd());
  882. EXPECT_THAT(
  883. tree,
  884. MatchParseTreeNodes(
  885. {MatchVariableDeclaration(
  886. MatchPatternBinding(MatchDeclaredName("x"), ":",
  887. MatchTupleLiteral(MatchLiteral("i32"),
  888. MatchTupleLiteralComma(),
  889. MatchLiteral("i32"),
  890. MatchTupleLiteralEnd())),
  891. MatchVariableInitializer(MatchTupleLiteral(
  892. MatchLiteral("1"), MatchTupleLiteralComma(),
  893. MatchLiteral("2"), MatchTupleLiteralEnd())),
  894. MatchDeclarationEnd()),
  895. MatchVariableDeclaration(
  896. MatchPatternBinding(
  897. MatchDeclaredName("y"), ":",
  898. MatchTupleLiteral(empty_tuple, MatchTupleLiteralComma(),
  899. empty_tuple, MatchTupleLiteralComma(),
  900. empty_tuple, MatchTupleLiteralEnd())),
  901. MatchDeclarationEnd()),
  902. MatchFileEnd()}));
  903. }
  904. auto GetAndDropLine(llvm::StringRef& s) -> std::string {
  905. auto newline_offset = s.find_first_of('\n');
  906. llvm::StringRef line = s.slice(0, newline_offset);
  907. if (newline_offset != llvm::StringRef::npos) {
  908. s = s.substr(newline_offset + 1);
  909. } else {
  910. s = "";
  911. }
  912. return line.str();
  913. }
  914. TEST_F(ParseTreeTest, Printing) {
  915. TokenizedBuffer tokens = GetTokenizedBuffer("fn F();");
  916. ParseTree tree = ParseTree::Parse(tokens, consumer);
  917. EXPECT_FALSE(tree.HasErrors());
  918. std::string print_storage;
  919. llvm::raw_string_ostream print_stream(print_storage);
  920. tree.Print(print_stream);
  921. llvm::StringRef print = print_stream.str();
  922. EXPECT_THAT(GetAndDropLine(print), StrEq("["));
  923. EXPECT_THAT(GetAndDropLine(print),
  924. StrEq("{node_index: 4, kind: 'FunctionDeclaration', text: 'fn', "
  925. "subtree_size: 5, children: ["));
  926. EXPECT_THAT(GetAndDropLine(print),
  927. StrEq(" {node_index: 0, kind: 'DeclaredName', text: 'F'},"));
  928. EXPECT_THAT(GetAndDropLine(print),
  929. StrEq(" {node_index: 2, kind: 'ParameterList', text: '(', "
  930. "subtree_size: 2, children: ["));
  931. EXPECT_THAT(GetAndDropLine(print),
  932. StrEq(" {node_index: 1, kind: 'ParameterListEnd', "
  933. "text: ')'}]},"));
  934. EXPECT_THAT(GetAndDropLine(print),
  935. StrEq(" {node_index: 3, kind: 'DeclarationEnd', text: ';'}]},"));
  936. EXPECT_THAT(GetAndDropLine(print),
  937. StrEq("{node_index: 5, kind: 'FileEnd', text: ''},"));
  938. EXPECT_THAT(GetAndDropLine(print), StrEq("]"));
  939. EXPECT_TRUE(print.empty()) << print;
  940. }
  941. TEST_F(ParseTreeTest, PrintingAsYAML) {
  942. TokenizedBuffer tokens = GetTokenizedBuffer("fn F();");
  943. ParseTree tree = ParseTree::Parse(tokens, consumer);
  944. EXPECT_FALSE(tree.HasErrors());
  945. std::string print_output;
  946. llvm::raw_string_ostream print_stream(print_output);
  947. tree.Print(print_stream);
  948. print_stream.flush();
  949. EXPECT_THAT(
  950. Yaml::Value::FromText(print_output),
  951. ElementsAre(Yaml::SequenceValue{
  952. Yaml::MappingValue{
  953. {"node_index", "4"},
  954. {"kind", "FunctionDeclaration"},
  955. {"text", "fn"},
  956. {"subtree_size", "5"},
  957. {"children",
  958. Yaml::SequenceValue{
  959. Yaml::MappingValue{{"node_index", "0"},
  960. {"kind", "DeclaredName"},
  961. {"text", "F"}},
  962. Yaml::MappingValue{{"node_index", "2"},
  963. {"kind", "ParameterList"},
  964. {"text", "("},
  965. {"subtree_size", "2"},
  966. {"children", //
  967. Yaml::SequenceValue{Yaml::MappingValue{
  968. {"node_index", "1"},
  969. {"kind", "ParameterListEnd"},
  970. {"text", ")"}}}}},
  971. Yaml::MappingValue{{"node_index", "3"},
  972. {"kind", "DeclarationEnd"},
  973. {"text", ";"}}}}},
  974. Yaml::MappingValue{{"node_index", "5"}, //
  975. {"kind", "FileEnd"},
  976. {"text", ""}}}));
  977. }
  978. } // namespace
  979. } // namespace Carbon