parse_tree_test.cpp 48 KB

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