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