parse_tree_test.cpp 48 KB

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