parse_tree_test.cpp 49 KB

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