Parser.cpp 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712
  1. /*
  2. * Copyright (c) 2020, the SerenityOS developers.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  22. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  23. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include "Parser.h"
  27. #include "Shell.h"
  28. #include <AK/AllOf.h>
  29. #include <AK/TemporaryChange.h>
  30. #include <ctype.h>
  31. #include <stdio.h>
  32. #include <unistd.h>
  33. namespace Shell {
  34. Parser::SavedOffset Parser::save_offset() const
  35. {
  36. return { m_offset, m_line };
  37. }
  38. char Parser::peek()
  39. {
  40. if (at_end())
  41. return 0;
  42. ASSERT(m_offset < m_input.length());
  43. auto ch = m_input[m_offset];
  44. if (ch == '\\' && m_input.length() > m_offset + 1 && m_input[m_offset + 1] == '\n') {
  45. m_offset += 2;
  46. ++m_line.line_number;
  47. m_line.line_column = 0;
  48. return peek();
  49. }
  50. return ch;
  51. }
  52. char Parser::consume()
  53. {
  54. if (at_end())
  55. return 0;
  56. auto ch = peek();
  57. ++m_offset;
  58. if (ch == '\n') {
  59. ++m_line.line_number;
  60. m_line.line_column = 0;
  61. } else {
  62. ++m_line.line_column;
  63. }
  64. return ch;
  65. }
  66. bool Parser::expect(char ch)
  67. {
  68. return expect(StringView { &ch, 1 });
  69. }
  70. bool Parser::expect(const StringView& expected)
  71. {
  72. auto offset_at_start = m_offset;
  73. auto line_at_start = line();
  74. if (expected.length() + m_offset > m_input.length())
  75. return false;
  76. for (size_t i = 0; i < expected.length(); ++i) {
  77. if (peek() != expected[i]) {
  78. restore_to(offset_at_start, line_at_start);
  79. return false;
  80. }
  81. consume();
  82. }
  83. return true;
  84. }
  85. template<typename A, typename... Args>
  86. NonnullRefPtr<A> Parser::create(Args... args)
  87. {
  88. return adopt(*new A(AST::Position { m_rule_start_offsets.last(), m_offset, m_rule_start_lines.last(), line() }, args...));
  89. }
  90. [[nodiscard]] OwnPtr<Parser::ScopedOffset> Parser::push_start()
  91. {
  92. return make<ScopedOffset>(m_rule_start_offsets, m_rule_start_lines, m_offset, m_line.line_number, m_line.line_column);
  93. }
  94. Parser::Offset Parser::current_position()
  95. {
  96. return Offset { m_offset, { m_line.line_number, m_line.line_column } };
  97. }
  98. static constexpr bool is_whitespace(char c)
  99. {
  100. return c == ' ' || c == '\t';
  101. }
  102. static constexpr bool is_digit(char c)
  103. {
  104. return c <= '9' && c >= '0';
  105. }
  106. static constexpr auto is_not(char c)
  107. {
  108. return [c](char ch) { return ch != c; };
  109. }
  110. static inline char to_byte(char a, char b)
  111. {
  112. char buf[3] { a, b, 0 };
  113. return strtol(buf, nullptr, 16);
  114. }
  115. RefPtr<AST::Node> Parser::parse()
  116. {
  117. m_offset = 0;
  118. m_line = { 0, 0 };
  119. auto toplevel = parse_toplevel();
  120. if (m_offset < m_input.length()) {
  121. // Parsing stopped midway, this is a syntax error.
  122. auto error_start = push_start();
  123. while (!at_end())
  124. consume();
  125. auto syntax_error_node = create<AST::SyntaxError>("Unexpected tokens past the end");
  126. if (!toplevel)
  127. toplevel = move(syntax_error_node);
  128. else if (!toplevel->is_syntax_error())
  129. toplevel->set_is_syntax_error(*syntax_error_node);
  130. }
  131. return toplevel;
  132. }
  133. RefPtr<AST::Node> Parser::parse_as_single_expression()
  134. {
  135. auto input = Shell::escape_token_for_double_quotes(m_input);
  136. Parser parser { input };
  137. return parser.parse_expression();
  138. }
  139. NonnullRefPtrVector<AST::Node> Parser::parse_as_multiple_expressions()
  140. {
  141. NonnullRefPtrVector<AST::Node> nodes;
  142. for (;;) {
  143. consume_while(is_whitespace);
  144. auto node = parse_expression();
  145. if (!node)
  146. node = parse_redirection();
  147. if (!node)
  148. return nodes;
  149. nodes.append(node.release_nonnull());
  150. }
  151. return nodes;
  152. }
  153. RefPtr<AST::Node> Parser::parse_toplevel()
  154. {
  155. auto rule_start = push_start();
  156. SequenceParseResult result;
  157. NonnullRefPtrVector<AST::Node> sequence;
  158. Vector<AST::Position> positions;
  159. do {
  160. result = parse_sequence();
  161. if (result.entries.is_empty())
  162. break;
  163. sequence.append(move(result.entries));
  164. positions.append(move(result.separator_positions));
  165. } while (result.decision == ShouldReadMoreSequences::Yes);
  166. if (sequence.is_empty())
  167. return nullptr;
  168. return create<AST::Execute>(
  169. create<AST::Sequence>(move(sequence), move(positions)));
  170. }
  171. Parser::SequenceParseResult Parser::parse_sequence()
  172. {
  173. consume_while(is_any_of(" \t\n;")); // ignore whitespaces or terminators without effect.
  174. NonnullRefPtrVector<AST::Node> left;
  175. auto rule_start = push_start();
  176. {
  177. auto var_decls = parse_variable_decls();
  178. if (var_decls)
  179. left.append(var_decls.release_nonnull());
  180. }
  181. auto pos_before_seps = save_offset();
  182. switch (peek()) {
  183. case '}':
  184. return { move(left), {}, ShouldReadMoreSequences::No };
  185. case ';':
  186. case '\n': {
  187. if (left.is_empty())
  188. break;
  189. consume_while(is_any_of("\n;"));
  190. auto pos_after_seps = save_offset();
  191. AST::Position separator_position { pos_before_seps.offset, pos_after_seps.offset, pos_before_seps.line, pos_after_seps.line };
  192. return { move(left), { move(separator_position) }, ShouldReadMoreSequences::Yes };
  193. }
  194. default:
  195. break;
  196. }
  197. auto first_entry = parse_function_decl();
  198. Vector<AST::Position> separator_positions;
  199. if (!first_entry)
  200. first_entry = parse_or_logical_sequence();
  201. if (!first_entry)
  202. return { move(left), {}, ShouldReadMoreSequences::No };
  203. left.append(first_entry.release_nonnull());
  204. separator_positions.empend(pos_before_seps.offset, pos_before_seps.offset, pos_before_seps.line, pos_before_seps.line);
  205. consume_while(is_whitespace);
  206. pos_before_seps = save_offset();
  207. switch (peek()) {
  208. case ';':
  209. case '\n': {
  210. consume_while(is_any_of("\n;"));
  211. auto pos_after_seps = save_offset();
  212. separator_positions.empend(pos_before_seps.offset, pos_after_seps.offset, pos_before_seps.line, pos_after_seps.line);
  213. return { move(left), move(separator_positions), ShouldReadMoreSequences::Yes };
  214. }
  215. case '&': {
  216. consume();
  217. auto pos_after_seps = save_offset();
  218. auto bg = create<AST::Background>(left.take_last()); // Execute Background
  219. left.append(move(bg));
  220. separator_positions.empend(pos_before_seps.offset, pos_after_seps.offset, pos_before_seps.line, pos_after_seps.line);
  221. return { move(left), move(separator_positions), ShouldReadMoreSequences::Yes };
  222. }
  223. default:
  224. return { move(left), move(separator_positions), ShouldReadMoreSequences::No };
  225. }
  226. }
  227. RefPtr<AST::Node> Parser::parse_variable_decls()
  228. {
  229. auto rule_start = push_start();
  230. consume_while(is_whitespace);
  231. auto pos_before_name = save_offset();
  232. auto var_name = consume_while(is_word_character);
  233. if (var_name.is_empty())
  234. return nullptr;
  235. if (!expect('=')) {
  236. restore_to(pos_before_name.offset, pos_before_name.line);
  237. return nullptr;
  238. }
  239. auto name_expr = create<AST::BarewordLiteral>(move(var_name));
  240. auto start = push_start();
  241. auto expression = parse_expression();
  242. if (!expression || expression->is_syntax_error()) {
  243. restore_to(*start);
  244. if (peek() == '(') {
  245. consume();
  246. auto command = parse_pipe_sequence();
  247. if (!command)
  248. restore_to(*start);
  249. else if (!expect(')'))
  250. command->set_is_syntax_error(*create<AST::SyntaxError>("Expected a terminating close paren", true));
  251. expression = command;
  252. }
  253. }
  254. if (!expression) {
  255. if (is_whitespace(peek())) {
  256. auto string_start = push_start();
  257. expression = create<AST::StringLiteral>("");
  258. } else {
  259. restore_to(pos_before_name.offset, pos_before_name.line);
  260. return nullptr;
  261. }
  262. }
  263. Vector<AST::VariableDeclarations::Variable> variables;
  264. variables.append({ move(name_expr), expression.release_nonnull() });
  265. if (consume_while(is_whitespace).is_empty())
  266. return create<AST::VariableDeclarations>(move(variables));
  267. auto rest = parse_variable_decls();
  268. if (!rest)
  269. return create<AST::VariableDeclarations>(move(variables));
  270. ASSERT(rest->is_variable_decls());
  271. auto* rest_decl = static_cast<AST::VariableDeclarations*>(rest.ptr());
  272. variables.append(rest_decl->variables());
  273. return create<AST::VariableDeclarations>(move(variables));
  274. }
  275. RefPtr<AST::Node> Parser::parse_function_decl()
  276. {
  277. auto rule_start = push_start();
  278. auto restore = [&] {
  279. restore_to(*rule_start);
  280. return nullptr;
  281. };
  282. consume_while(is_whitespace);
  283. auto pos_before_name = save_offset();
  284. auto function_name = consume_while(is_word_character);
  285. auto pos_after_name = save_offset();
  286. if (function_name.is_empty())
  287. return restore();
  288. if (!expect('('))
  289. return restore();
  290. Vector<AST::FunctionDeclaration::NameWithPosition> arguments;
  291. for (;;) {
  292. consume_while(is_whitespace);
  293. if (expect(')'))
  294. break;
  295. auto name_offset = m_offset;
  296. auto start_line = line();
  297. auto arg_name = consume_while(is_word_character);
  298. if (arg_name.is_empty()) {
  299. // FIXME: Should this be a syntax error, or just return?
  300. return restore();
  301. }
  302. arguments.append({ arg_name, { name_offset, m_offset, start_line, line() } });
  303. }
  304. consume_while(is_whitespace);
  305. {
  306. RefPtr<AST::Node> syntax_error;
  307. {
  308. auto obrace_error_start = push_start();
  309. syntax_error = create<AST::SyntaxError>("Expected an open brace '{' to start a function body", true);
  310. }
  311. if (!expect('{')) {
  312. return create<AST::FunctionDeclaration>(
  313. AST::FunctionDeclaration::NameWithPosition {
  314. move(function_name),
  315. { pos_before_name.offset, pos_after_name.offset, pos_before_name.line, pos_after_name.line } },
  316. move(arguments),
  317. move(syntax_error));
  318. }
  319. }
  320. TemporaryChange controls { m_continuation_controls_allowed, false };
  321. auto body = parse_toplevel();
  322. {
  323. RefPtr<AST::SyntaxError> syntax_error;
  324. {
  325. auto cbrace_error_start = push_start();
  326. syntax_error = create<AST::SyntaxError>("Expected a close brace '}' to end a function body", true);
  327. }
  328. if (!expect('}')) {
  329. if (body)
  330. body->set_is_syntax_error(*syntax_error);
  331. else
  332. body = move(syntax_error);
  333. return create<AST::FunctionDeclaration>(
  334. AST::FunctionDeclaration::NameWithPosition {
  335. move(function_name),
  336. { pos_before_name.offset, pos_after_name.offset, pos_before_name.line, pos_after_name.line } },
  337. move(arguments),
  338. move(body));
  339. }
  340. }
  341. return create<AST::FunctionDeclaration>(
  342. AST::FunctionDeclaration::NameWithPosition {
  343. move(function_name),
  344. { pos_before_name.offset, pos_after_name.offset, pos_before_name.line, pos_after_name.line } },
  345. move(arguments),
  346. move(body));
  347. }
  348. RefPtr<AST::Node> Parser::parse_or_logical_sequence()
  349. {
  350. consume_while(is_whitespace);
  351. auto rule_start = push_start();
  352. auto and_sequence = parse_and_logical_sequence();
  353. if (!and_sequence)
  354. return nullptr;
  355. consume_while(is_whitespace);
  356. auto pos_before_or = save_offset();
  357. if (!expect("||"))
  358. return and_sequence;
  359. auto pos_after_or = save_offset();
  360. auto right_and_sequence = parse_and_logical_sequence();
  361. if (!right_and_sequence)
  362. right_and_sequence = create<AST::SyntaxError>("Expected an expression after '||'", true);
  363. return create<AST::Or>(
  364. and_sequence.release_nonnull(),
  365. right_and_sequence.release_nonnull(),
  366. AST::Position { pos_before_or.offset, pos_after_or.offset, pos_before_or.line, pos_after_or.line });
  367. }
  368. RefPtr<AST::Node> Parser::parse_and_logical_sequence()
  369. {
  370. consume_while(is_whitespace);
  371. auto rule_start = push_start();
  372. auto pipe_sequence = parse_pipe_sequence();
  373. if (!pipe_sequence)
  374. return nullptr;
  375. consume_while(is_whitespace);
  376. auto pos_before_and = save_offset();
  377. if (!expect("&&"))
  378. return pipe_sequence;
  379. auto pos_after_end = save_offset();
  380. auto right_and_sequence = parse_and_logical_sequence();
  381. if (!right_and_sequence)
  382. right_and_sequence = create<AST::SyntaxError>("Expected an expression after '&&'", true);
  383. return create<AST::And>(
  384. pipe_sequence.release_nonnull(),
  385. right_and_sequence.release_nonnull(),
  386. AST::Position { pos_before_and.offset, pos_after_end.offset, pos_before_and.line, pos_after_end.line });
  387. }
  388. RefPtr<AST::Node> Parser::parse_pipe_sequence()
  389. {
  390. auto rule_start = push_start();
  391. auto left = parse_control_structure();
  392. if (!left) {
  393. if (auto cmd = parse_command())
  394. left = cmd;
  395. else
  396. return nullptr;
  397. }
  398. consume_while(is_whitespace);
  399. if (peek() != '|')
  400. return left;
  401. auto before_pipe = save_offset();
  402. consume();
  403. if (auto pipe_seq = parse_pipe_sequence()) {
  404. return create<AST::Pipe>(left.release_nonnull(), pipe_seq.release_nonnull()); // Pipe
  405. }
  406. restore_to(before_pipe.offset, before_pipe.line);
  407. return left;
  408. }
  409. RefPtr<AST::Node> Parser::parse_command()
  410. {
  411. auto rule_start = push_start();
  412. consume_while(is_whitespace);
  413. auto redir = parse_redirection();
  414. if (!redir) {
  415. auto list_expr = parse_list_expression();
  416. if (!list_expr)
  417. return nullptr;
  418. auto cast = create<AST::CastToCommand>(list_expr.release_nonnull()); // Cast List Command
  419. auto next_command = parse_command();
  420. if (!next_command)
  421. return cast;
  422. return create<AST::Join>(move(cast), next_command.release_nonnull()); // Join List Command
  423. }
  424. auto command = parse_command();
  425. if (!command)
  426. return redir;
  427. return create<AST::Join>(redir.release_nonnull(), command.release_nonnull()); // Join Command Command
  428. }
  429. RefPtr<AST::Node> Parser::parse_control_structure()
  430. {
  431. auto rule_start = push_start();
  432. consume_while(is_whitespace);
  433. if (auto control = parse_continuation_control())
  434. return control;
  435. if (auto for_loop = parse_for_loop())
  436. return for_loop;
  437. if (auto loop = parse_loop_loop())
  438. return loop;
  439. if (auto if_expr = parse_if_expr())
  440. return if_expr;
  441. if (auto subshell = parse_subshell())
  442. return subshell;
  443. if (auto match = parse_match_expr())
  444. return match;
  445. return nullptr;
  446. }
  447. RefPtr<AST::Node> Parser::parse_continuation_control()
  448. {
  449. if (!m_continuation_controls_allowed)
  450. return nullptr;
  451. auto rule_start = push_start();
  452. if (expect("break")) {
  453. {
  454. auto break_end = push_start();
  455. if (consume_while(is_any_of(" \t\n;")).is_empty()) {
  456. restore_to(*rule_start);
  457. return nullptr;
  458. }
  459. restore_to(*break_end);
  460. }
  461. return create<AST::ContinuationControl>(AST::ContinuationControl::Break);
  462. }
  463. if (expect("continue")) {
  464. {
  465. auto continue_end = push_start();
  466. if (consume_while(is_any_of(" \t\n;")).is_empty()) {
  467. restore_to(*rule_start);
  468. return nullptr;
  469. }
  470. restore_to(*continue_end);
  471. }
  472. return create<AST::ContinuationControl>(AST::ContinuationControl::Continue);
  473. }
  474. return nullptr;
  475. }
  476. RefPtr<AST::Node> Parser::parse_for_loop()
  477. {
  478. auto rule_start = push_start();
  479. if (!expect("for"))
  480. return nullptr;
  481. if (consume_while(is_any_of(" \t\n")).is_empty()) {
  482. restore_to(*rule_start);
  483. return nullptr;
  484. }
  485. auto variable_name = consume_while(is_word_character);
  486. Optional<AST::Position> in_start_position;
  487. if (variable_name.is_empty()) {
  488. variable_name = "it";
  489. } else {
  490. consume_while(is_whitespace);
  491. auto in_error_start = push_start();
  492. if (!expect("in")) {
  493. auto syntax_error = create<AST::SyntaxError>("Expected 'in' after a variable name in a 'for' loop", true);
  494. return create<AST::ForLoop>(move(variable_name), move(syntax_error), nullptr); // ForLoop Var Iterated Block
  495. }
  496. in_start_position = AST::Position { in_error_start->offset, m_offset, in_error_start->line, line() };
  497. }
  498. consume_while(is_whitespace);
  499. RefPtr<AST::Node> iterated_expression;
  500. {
  501. auto iter_error_start = push_start();
  502. iterated_expression = parse_expression();
  503. if (!iterated_expression)
  504. iterated_expression = create<AST::SyntaxError>("Expected an expression in 'for' loop", true);
  505. }
  506. consume_while(is_any_of(" \t\n"));
  507. {
  508. auto obrace_error_start = push_start();
  509. if (!expect('{')) {
  510. auto syntax_error = create<AST::SyntaxError>("Expected an open brace '{' to start a 'for' loop body", true);
  511. return create<AST::ForLoop>(move(variable_name), move(iterated_expression), move(syntax_error), move(in_start_position)); // ForLoop Var Iterated Block
  512. }
  513. }
  514. TemporaryChange controls { m_continuation_controls_allowed, true };
  515. auto body = parse_toplevel();
  516. {
  517. auto cbrace_error_start = push_start();
  518. if (!expect('}')) {
  519. auto error_start = push_start();
  520. auto syntax_error = create<AST::SyntaxError>("Expected a close brace '}' to end a 'for' loop body", true);
  521. if (body)
  522. body->set_is_syntax_error(*syntax_error);
  523. else
  524. body = syntax_error;
  525. }
  526. }
  527. return create<AST::ForLoop>(move(variable_name), move(iterated_expression), move(body), move(in_start_position)); // ForLoop Var Iterated Block
  528. }
  529. RefPtr<AST::Node> Parser::parse_loop_loop()
  530. {
  531. auto rule_start = push_start();
  532. if (!expect("loop"))
  533. return nullptr;
  534. if (consume_while(is_any_of(" \t\n")).is_empty()) {
  535. restore_to(*rule_start);
  536. return nullptr;
  537. }
  538. {
  539. auto obrace_error_start = push_start();
  540. if (!expect('{')) {
  541. auto syntax_error = create<AST::SyntaxError>("Expected an open brace '{' to start a 'loop' loop body", true);
  542. return create<AST::ForLoop>(String::empty(), nullptr, move(syntax_error), Optional<AST::Position> {}); // ForLoop null null Block
  543. }
  544. }
  545. TemporaryChange controls { m_continuation_controls_allowed, true };
  546. auto body = parse_toplevel();
  547. {
  548. auto cbrace_error_start = push_start();
  549. if (!expect('}')) {
  550. auto error_start = push_start();
  551. auto syntax_error = create<AST::SyntaxError>("Expected a close brace '}' to end a 'loop' loop body", true);
  552. if (body)
  553. body->set_is_syntax_error(*syntax_error);
  554. else
  555. body = syntax_error;
  556. }
  557. }
  558. return create<AST::ForLoop>(String::empty(), nullptr, move(body), Optional<AST::Position> {}); // ForLoop null null Block
  559. }
  560. RefPtr<AST::Node> Parser::parse_if_expr()
  561. {
  562. auto rule_start = push_start();
  563. if (!expect("if"))
  564. return nullptr;
  565. if (consume_while(is_any_of(" \t\n")).is_empty()) {
  566. restore_to(*rule_start);
  567. return nullptr;
  568. }
  569. RefPtr<AST::Node> condition;
  570. {
  571. auto cond_error_start = push_start();
  572. condition = parse_or_logical_sequence();
  573. if (!condition)
  574. condition = create<AST::SyntaxError>("Expected a logical sequence after 'if'", true);
  575. }
  576. auto parse_braced_toplevel = [&]() -> RefPtr<AST::Node> {
  577. RefPtr<AST::Node> body;
  578. {
  579. auto obrace_error_start = push_start();
  580. if (!expect('{')) {
  581. body = create<AST::SyntaxError>("Expected an open brace '{' to start an 'if' true branch", true);
  582. }
  583. }
  584. if (!body)
  585. body = parse_toplevel();
  586. {
  587. auto cbrace_error_start = push_start();
  588. if (!expect('}')) {
  589. auto error_start = push_start();
  590. RefPtr<AST::SyntaxError> syntax_error = create<AST::SyntaxError>("Expected a close brace '}' to end an 'if' true branch", true);
  591. if (body)
  592. body->set_is_syntax_error(*syntax_error);
  593. else
  594. body = syntax_error;
  595. }
  596. }
  597. return body;
  598. };
  599. consume_while(is_any_of(" \t\n"));
  600. auto true_branch = parse_braced_toplevel();
  601. auto end_before_else = m_offset;
  602. auto line_before_else = line();
  603. consume_while(is_any_of(" \t\n"));
  604. Optional<AST::Position> else_position;
  605. {
  606. auto else_start = push_start();
  607. if (expect("else"))
  608. else_position = AST::Position { else_start->offset, m_offset, else_start->line, line() };
  609. else
  610. restore_to(end_before_else, line_before_else);
  611. }
  612. if (else_position.has_value()) {
  613. consume_while(is_any_of(" \t\n"));
  614. if (peek() == '{') {
  615. auto false_branch = parse_braced_toplevel();
  616. return create<AST::IfCond>(else_position, condition.release_nonnull(), move(true_branch), move(false_branch)); // If expr true_branch Else false_branch
  617. }
  618. auto else_if_branch = parse_if_expr();
  619. return create<AST::IfCond>(else_position, condition.release_nonnull(), move(true_branch), move(else_if_branch)); // If expr true_branch Else If ...
  620. }
  621. return create<AST::IfCond>(else_position, condition.release_nonnull(), move(true_branch), nullptr); // If expr true_branch
  622. }
  623. RefPtr<AST::Node> Parser::parse_subshell()
  624. {
  625. auto rule_start = push_start();
  626. if (!expect('{'))
  627. return nullptr;
  628. auto body = parse_toplevel();
  629. {
  630. auto cbrace_error_start = push_start();
  631. if (!expect('}')) {
  632. auto error_start = push_start();
  633. RefPtr<AST::SyntaxError> syntax_error = create<AST::SyntaxError>("Expected a close brace '}' to end a subshell", true);
  634. if (body)
  635. body->set_is_syntax_error(*syntax_error);
  636. else
  637. body = syntax_error;
  638. }
  639. }
  640. return create<AST::Subshell>(move(body));
  641. }
  642. RefPtr<AST::Node> Parser::parse_match_expr()
  643. {
  644. auto rule_start = push_start();
  645. if (!expect("match"))
  646. return nullptr;
  647. if (consume_while(is_whitespace).is_empty()) {
  648. restore_to(*rule_start);
  649. return nullptr;
  650. }
  651. auto match_expression = parse_expression();
  652. if (!match_expression) {
  653. return create<AST::MatchExpr>(
  654. create<AST::SyntaxError>("Expected an expression after 'match'", true),
  655. String {}, Optional<AST::Position> {}, Vector<AST::MatchEntry> {});
  656. }
  657. consume_while(is_any_of(" \t\n"));
  658. String match_name;
  659. Optional<AST::Position> as_position;
  660. auto as_start = m_offset;
  661. auto as_line = line();
  662. if (expect("as")) {
  663. as_position = AST::Position { as_start, m_offset, as_line, line() };
  664. if (consume_while(is_any_of(" \t\n")).is_empty()) {
  665. auto node = create<AST::MatchExpr>(
  666. match_expression.release_nonnull(),
  667. String {}, move(as_position), Vector<AST::MatchEntry> {});
  668. node->set_is_syntax_error(create<AST::SyntaxError>("Expected whitespace after 'as' in 'match'", true));
  669. return node;
  670. }
  671. match_name = consume_while(is_word_character);
  672. if (match_name.is_empty()) {
  673. auto node = create<AST::MatchExpr>(
  674. match_expression.release_nonnull(),
  675. String {}, move(as_position), Vector<AST::MatchEntry> {});
  676. node->set_is_syntax_error(create<AST::SyntaxError>("Expected an identifier after 'as' in 'match'", true));
  677. return node;
  678. }
  679. }
  680. consume_while(is_any_of(" \t\n"));
  681. if (!expect('{')) {
  682. auto node = create<AST::MatchExpr>(
  683. match_expression.release_nonnull(),
  684. move(match_name), move(as_position), Vector<AST::MatchEntry> {});
  685. node->set_is_syntax_error(create<AST::SyntaxError>("Expected an open brace '{' to start a 'match' entry list", true));
  686. return node;
  687. }
  688. consume_while(is_any_of(" \t\n"));
  689. Vector<AST::MatchEntry> entries;
  690. for (;;) {
  691. auto entry = parse_match_entry();
  692. consume_while(is_any_of(" \t\n"));
  693. if (entry.options.is_empty())
  694. break;
  695. entries.append(entry);
  696. }
  697. consume_while(is_any_of(" \t\n"));
  698. if (!expect('}')) {
  699. auto node = create<AST::MatchExpr>(
  700. match_expression.release_nonnull(),
  701. move(match_name), move(as_position), move(entries));
  702. node->set_is_syntax_error(create<AST::SyntaxError>("Expected a close brace '}' to end a 'match' entry list", true));
  703. return node;
  704. }
  705. return create<AST::MatchExpr>(match_expression.release_nonnull(), move(match_name), move(as_position), move(entries));
  706. }
  707. AST::MatchEntry Parser::parse_match_entry()
  708. {
  709. auto rule_start = push_start();
  710. NonnullRefPtrVector<AST::Node> patterns;
  711. Vector<AST::Position> pipe_positions;
  712. Optional<Vector<String>> match_names;
  713. Optional<AST::Position> match_as_position;
  714. auto pattern = parse_match_pattern();
  715. if (!pattern)
  716. return { {}, {}, {}, {}, create<AST::SyntaxError>("Expected a pattern in 'match' body", true) };
  717. patterns.append(pattern.release_nonnull());
  718. consume_while(is_any_of(" \t\n"));
  719. auto previous_pipe_start_position = m_offset;
  720. auto previous_pipe_start_line = line();
  721. RefPtr<AST::SyntaxError> error;
  722. while (expect('|')) {
  723. pipe_positions.append({ previous_pipe_start_position, m_offset, previous_pipe_start_line, line() });
  724. consume_while(is_any_of(" \t\n"));
  725. auto pattern = parse_match_pattern();
  726. if (!pattern) {
  727. error = create<AST::SyntaxError>("Expected a pattern to follow '|' in 'match' body", true);
  728. break;
  729. }
  730. consume_while(is_any_of(" \t\n"));
  731. patterns.append(pattern.release_nonnull());
  732. previous_pipe_start_line = line();
  733. previous_pipe_start_position = m_offset;
  734. }
  735. consume_while(is_any_of(" \t\n"));
  736. auto as_start_position = m_offset;
  737. auto as_start_line = line();
  738. if (expect("as")) {
  739. match_as_position = AST::Position { as_start_position, m_offset, as_start_line, line() };
  740. consume_while(is_any_of(" \t\n"));
  741. if (!expect('(')) {
  742. if (!error)
  743. error = create<AST::SyntaxError>("Expected an explicit list of identifiers after a pattern 'as'");
  744. } else {
  745. match_names = Vector<String>();
  746. for (;;) {
  747. consume_while(is_whitespace);
  748. auto name = consume_while(is_word_character);
  749. if (name.is_empty())
  750. break;
  751. match_names.value().append(move(name));
  752. }
  753. if (!expect(')')) {
  754. if (!error)
  755. error = create<AST::SyntaxError>("Expected a close paren ')' to end the identifier list of pattern 'as'", true);
  756. }
  757. }
  758. consume_while(is_any_of(" \t\n"));
  759. }
  760. if (!expect('{')) {
  761. if (!error)
  762. error = create<AST::SyntaxError>("Expected an open brace '{' to start a match entry body", true);
  763. }
  764. auto body = parse_toplevel();
  765. if (!expect('}')) {
  766. if (!error)
  767. error = create<AST::SyntaxError>("Expected a close brace '}' to end a match entry body", true);
  768. }
  769. if (body && error)
  770. body->set_is_syntax_error(*error);
  771. else if (error)
  772. body = error;
  773. return { move(patterns), move(match_names), move(match_as_position), move(pipe_positions), move(body) };
  774. }
  775. RefPtr<AST::Node> Parser::parse_match_pattern()
  776. {
  777. return parse_expression();
  778. }
  779. RefPtr<AST::Node> Parser::parse_redirection()
  780. {
  781. auto rule_start = push_start();
  782. auto pipe_fd = 0;
  783. auto number = consume_while(is_digit);
  784. if (number.is_empty()) {
  785. pipe_fd = -1;
  786. } else {
  787. auto fd = number.to_int();
  788. pipe_fd = fd.value_or(-1);
  789. }
  790. switch (peek()) {
  791. case '>': {
  792. consume();
  793. if (peek() == '>') {
  794. consume();
  795. consume_while(is_whitespace);
  796. pipe_fd = pipe_fd >= 0 ? pipe_fd : STDOUT_FILENO;
  797. auto path = parse_expression();
  798. if (!path) {
  799. if (!at_end()) {
  800. // Eat a character and hope the problem goes away
  801. consume();
  802. }
  803. path = create<AST::SyntaxError>("Expected a path after redirection", true);
  804. }
  805. return create<AST::WriteAppendRedirection>(pipe_fd, path.release_nonnull()); // Redirection WriteAppend
  806. }
  807. if (peek() == '&') {
  808. consume();
  809. // FIXME: 'fd>&-' Syntax not the best. needs discussion.
  810. if (peek() == '-') {
  811. consume();
  812. pipe_fd = pipe_fd >= 0 ? pipe_fd : STDOUT_FILENO;
  813. return create<AST::CloseFdRedirection>(pipe_fd); // Redirection CloseFd
  814. }
  815. int dest_pipe_fd = 0;
  816. auto number = consume_while(is_digit);
  817. pipe_fd = pipe_fd >= 0 ? pipe_fd : STDOUT_FILENO;
  818. if (number.is_empty()) {
  819. dest_pipe_fd = -1;
  820. } else {
  821. auto fd = number.to_int();
  822. dest_pipe_fd = fd.value_or(-1);
  823. }
  824. auto redir = create<AST::Fd2FdRedirection>(pipe_fd, dest_pipe_fd); // Redirection Fd2Fd
  825. if (dest_pipe_fd == -1)
  826. redir->set_is_syntax_error(*create<AST::SyntaxError>("Expected a file descriptor"));
  827. return redir;
  828. }
  829. consume_while(is_whitespace);
  830. pipe_fd = pipe_fd >= 0 ? pipe_fd : STDOUT_FILENO;
  831. auto path = parse_expression();
  832. if (!path) {
  833. if (!at_end()) {
  834. // Eat a character and hope the problem goes away
  835. consume();
  836. }
  837. path = create<AST::SyntaxError>("Expected a path after redirection", true);
  838. }
  839. return create<AST::WriteRedirection>(pipe_fd, path.release_nonnull()); // Redirection Write
  840. }
  841. case '<': {
  842. consume();
  843. enum {
  844. Read,
  845. ReadWrite,
  846. } mode { Read };
  847. if (peek() == '>') {
  848. mode = ReadWrite;
  849. consume();
  850. }
  851. consume_while(is_whitespace);
  852. pipe_fd = pipe_fd >= 0 ? pipe_fd : STDIN_FILENO;
  853. auto path = parse_expression();
  854. if (!path) {
  855. if (!at_end()) {
  856. // Eat a character and hope the problem goes away
  857. consume();
  858. }
  859. path = create<AST::SyntaxError>("Expected a path after redirection", true);
  860. }
  861. if (mode == Read)
  862. return create<AST::ReadRedirection>(pipe_fd, path.release_nonnull()); // Redirection Read
  863. return create<AST::ReadWriteRedirection>(pipe_fd, path.release_nonnull()); // Redirection ReadWrite
  864. }
  865. default:
  866. restore_to(*rule_start);
  867. return nullptr;
  868. }
  869. }
  870. RefPtr<AST::Node> Parser::parse_list_expression()
  871. {
  872. consume_while(is_whitespace);
  873. auto rule_start = push_start();
  874. Vector<NonnullRefPtr<AST::Node>> nodes;
  875. do {
  876. auto expr = parse_expression();
  877. if (!expr)
  878. break;
  879. nodes.append(expr.release_nonnull());
  880. } while (!consume_while(is_whitespace).is_empty());
  881. if (nodes.is_empty())
  882. return nullptr;
  883. return create<AST::ListConcatenate>(move(nodes)); // Concatenate List
  884. }
  885. RefPtr<AST::Node> Parser::parse_expression()
  886. {
  887. auto rule_start = push_start();
  888. if (m_rule_start_offsets.size() > max_allowed_nested_rule_depth)
  889. return create<AST::SyntaxError>(String::formatted("Expression nested too deep (max allowed is {})", max_allowed_nested_rule_depth));
  890. auto starting_char = peek();
  891. auto read_concat = [&](auto&& expr) -> NonnullRefPtr<AST::Node> {
  892. if (is_whitespace(peek()))
  893. return move(expr);
  894. if (auto next_expr = parse_expression())
  895. return create<AST::Juxtaposition>(move(expr), next_expr.release_nonnull());
  896. return move(expr);
  897. };
  898. if (strchr("&|)} ;<>\n", starting_char) != nullptr)
  899. return nullptr;
  900. if (m_extra_chars_not_allowed_in_barewords.contains_slow(starting_char))
  901. return nullptr;
  902. if (m_is_in_brace_expansion_spec && next_is(".."))
  903. return nullptr;
  904. if (isdigit(starting_char)) {
  905. ScopedValueRollback offset_rollback { m_offset };
  906. auto redir = parse_redirection();
  907. if (redir)
  908. return nullptr;
  909. }
  910. if (starting_char == '$') {
  911. if (auto variable = parse_variable())
  912. return read_concat(variable.release_nonnull());
  913. if (auto inline_exec = parse_evaluate())
  914. return read_concat(inline_exec.release_nonnull());
  915. }
  916. if (starting_char == '#')
  917. return parse_comment();
  918. if (starting_char == '(') {
  919. consume();
  920. auto list = parse_list_expression();
  921. if (!expect(')')) {
  922. restore_to(*rule_start);
  923. return nullptr;
  924. }
  925. return read_concat(create<AST::CastToList>(move(list))); // Cast To List
  926. }
  927. if (starting_char == '!') {
  928. if (auto designator = parse_history_designator())
  929. return designator;
  930. }
  931. if (auto composite = parse_string_composite())
  932. return read_concat(composite.release_nonnull());
  933. return nullptr;
  934. }
  935. RefPtr<AST::Node> Parser::parse_string_composite()
  936. {
  937. auto rule_start = push_start();
  938. if (auto string = parse_string()) {
  939. if (auto next_part = parse_string_composite())
  940. return create<AST::Juxtaposition>(string.release_nonnull(), next_part.release_nonnull()); // Concatenate String StringComposite
  941. return string;
  942. }
  943. if (auto variable = parse_variable()) {
  944. if (auto next_part = parse_string_composite())
  945. return create<AST::Juxtaposition>(variable.release_nonnull(), next_part.release_nonnull()); // Concatenate Variable StringComposite
  946. return variable;
  947. }
  948. if (auto glob = parse_glob()) {
  949. if (auto next_part = parse_string_composite())
  950. return create<AST::Juxtaposition>(glob.release_nonnull(), next_part.release_nonnull()); // Concatenate Glob StringComposite
  951. return glob;
  952. }
  953. if (auto expansion = parse_brace_expansion()) {
  954. if (auto next_part = parse_string_composite())
  955. return create<AST::Juxtaposition>(expansion.release_nonnull(), next_part.release_nonnull()); // Concatenate BraceExpansion StringComposite
  956. return expansion;
  957. }
  958. if (auto bareword = parse_bareword()) {
  959. if (auto next_part = parse_string_composite())
  960. return create<AST::Juxtaposition>(bareword.release_nonnull(), next_part.release_nonnull()); // Concatenate Bareword StringComposite
  961. return bareword;
  962. }
  963. if (auto inline_command = parse_evaluate()) {
  964. if (auto next_part = parse_string_composite())
  965. return create<AST::Juxtaposition>(inline_command.release_nonnull(), next_part.release_nonnull()); // Concatenate Execute StringComposite
  966. return inline_command;
  967. }
  968. return nullptr;
  969. }
  970. RefPtr<AST::Node> Parser::parse_string()
  971. {
  972. auto rule_start = push_start();
  973. if (at_end())
  974. return nullptr;
  975. if (peek() == '"') {
  976. consume();
  977. auto inner = parse_doublequoted_string_inner();
  978. if (!inner)
  979. inner = create<AST::SyntaxError>("Unexpected EOF in string", true);
  980. if (!expect('"')) {
  981. inner = create<AST::DoubleQuotedString>(move(inner));
  982. inner->set_is_syntax_error(*create<AST::SyntaxError>("Expected a terminating double quote", true));
  983. return inner;
  984. }
  985. return create<AST::DoubleQuotedString>(move(inner)); // Double Quoted String
  986. }
  987. if (peek() == '\'') {
  988. consume();
  989. auto text = consume_while(is_not('\''));
  990. bool is_error = false;
  991. if (!expect('\''))
  992. is_error = true;
  993. auto result = create<AST::StringLiteral>(move(text)); // String Literal
  994. if (is_error)
  995. result->set_is_syntax_error(*create<AST::SyntaxError>("Expected a terminating single quote", true));
  996. return move(result);
  997. }
  998. return nullptr;
  999. }
  1000. RefPtr<AST::Node> Parser::parse_doublequoted_string_inner()
  1001. {
  1002. auto rule_start = push_start();
  1003. if (at_end())
  1004. return nullptr;
  1005. StringBuilder builder;
  1006. while (!at_end() && peek() != '"') {
  1007. if (peek() == '\\') {
  1008. consume();
  1009. if (at_end()) {
  1010. break;
  1011. }
  1012. auto ch = consume();
  1013. switch (ch) {
  1014. case '\\':
  1015. default:
  1016. builder.append(ch);
  1017. break;
  1018. case 'x': {
  1019. if (m_input.length() <= m_offset + 2)
  1020. break;
  1021. auto first_nibble = tolower(consume());
  1022. auto second_nibble = tolower(consume());
  1023. if (!isxdigit(first_nibble) || !isxdigit(second_nibble)) {
  1024. builder.append(first_nibble);
  1025. builder.append(second_nibble);
  1026. break;
  1027. }
  1028. builder.append(to_byte(first_nibble, second_nibble));
  1029. break;
  1030. }
  1031. case 'a':
  1032. builder.append('\a');
  1033. break;
  1034. case 'b':
  1035. builder.append('\b');
  1036. break;
  1037. case 'e':
  1038. builder.append('\x1b');
  1039. break;
  1040. case 'f':
  1041. builder.append('\f');
  1042. break;
  1043. case 'r':
  1044. builder.append('\r');
  1045. break;
  1046. case 'n':
  1047. builder.append('\n');
  1048. break;
  1049. }
  1050. continue;
  1051. }
  1052. if (peek() == '$') {
  1053. auto string_literal = create<AST::StringLiteral>(builder.to_string()); // String Literal
  1054. if (auto variable = parse_variable()) {
  1055. auto inner = create<AST::StringPartCompose>(
  1056. move(string_literal),
  1057. variable.release_nonnull()); // Compose String Variable
  1058. if (auto string = parse_doublequoted_string_inner()) {
  1059. return create<AST::StringPartCompose>(move(inner), string.release_nonnull()); // Compose Composition Composition
  1060. }
  1061. return inner;
  1062. }
  1063. if (auto evaluate = parse_evaluate()) {
  1064. auto composition = create<AST::StringPartCompose>(
  1065. move(string_literal),
  1066. evaluate.release_nonnull()); // Compose String Sequence
  1067. if (auto string = parse_doublequoted_string_inner()) {
  1068. return create<AST::StringPartCompose>(move(composition), string.release_nonnull()); // Compose Composition Composition
  1069. }
  1070. return composition;
  1071. }
  1072. }
  1073. builder.append(consume());
  1074. }
  1075. return create<AST::StringLiteral>(builder.to_string()); // String Literal
  1076. }
  1077. RefPtr<AST::Node> Parser::parse_variable()
  1078. {
  1079. auto rule_start = push_start();
  1080. if (at_end())
  1081. return nullptr;
  1082. if (peek() != '$')
  1083. return nullptr;
  1084. consume();
  1085. switch (peek()) {
  1086. case '$':
  1087. case '?':
  1088. case '*':
  1089. case '#':
  1090. return create<AST::SpecialVariable>(consume()); // Variable Special
  1091. default:
  1092. break;
  1093. }
  1094. auto name = consume_while(is_word_character);
  1095. if (name.length() == 0) {
  1096. restore_to(rule_start->offset, rule_start->line);
  1097. return nullptr;
  1098. }
  1099. return create<AST::SimpleVariable>(move(name)); // Variable Simple
  1100. }
  1101. RefPtr<AST::Node> Parser::parse_evaluate()
  1102. {
  1103. auto rule_start = push_start();
  1104. if (at_end())
  1105. return nullptr;
  1106. if (peek() != '$')
  1107. return nullptr;
  1108. consume();
  1109. if (peek() == '(') {
  1110. consume();
  1111. auto inner = parse_pipe_sequence();
  1112. if (!inner)
  1113. inner = create<AST::SyntaxError>("Unexpected EOF in list", true);
  1114. if (!expect(')'))
  1115. inner->set_is_syntax_error(*create<AST::SyntaxError>("Expected a terminating close paren", true));
  1116. return create<AST::Execute>(inner.release_nonnull(), true);
  1117. }
  1118. auto inner = parse_expression();
  1119. if (!inner) {
  1120. inner = create<AST::SyntaxError>("Expected a command", true);
  1121. } else {
  1122. if (inner->is_list()) {
  1123. auto execute_inner = create<AST::Execute>(inner.release_nonnull(), true);
  1124. inner = move(execute_inner);
  1125. } else {
  1126. auto dyn_inner = create<AST::DynamicEvaluate>(inner.release_nonnull());
  1127. inner = move(dyn_inner);
  1128. }
  1129. }
  1130. return inner;
  1131. }
  1132. RefPtr<AST::Node> Parser::parse_history_designator()
  1133. {
  1134. auto rule_start = push_start();
  1135. ASSERT(peek() == '!');
  1136. consume();
  1137. // Event selector
  1138. AST::HistorySelector selector;
  1139. RefPtr<AST::Node> syntax_error;
  1140. selector.event.kind = AST::HistorySelector::EventKind::StartingStringLookup;
  1141. selector.event.text_position = { m_offset, m_offset, m_line, m_line };
  1142. selector.word_selector_range = {
  1143. { AST::HistorySelector::WordSelectorKind::Index, 0, { m_offset, m_offset, m_line, m_line } },
  1144. AST::HistorySelector::WordSelector {
  1145. AST::HistorySelector::WordSelectorKind::Last, 0, { m_offset, m_offset, m_line, m_line } },
  1146. };
  1147. switch (peek()) {
  1148. case '!':
  1149. consume();
  1150. selector.event.kind = AST::HistorySelector::EventKind::IndexFromEnd;
  1151. selector.event.index = 0;
  1152. selector.event.text = "!";
  1153. break;
  1154. case '?':
  1155. consume();
  1156. selector.event.kind = AST::HistorySelector::EventKind::ContainingStringLookup;
  1157. [[fallthrough]];
  1158. default: {
  1159. TemporaryChange chars_change { m_extra_chars_not_allowed_in_barewords, { ':' } };
  1160. auto bareword = parse_bareword();
  1161. if (!bareword || !bareword->is_bareword()) {
  1162. restore_to(*rule_start);
  1163. return nullptr;
  1164. }
  1165. selector.event.text = static_ptr_cast<AST::BarewordLiteral>(bareword)->text();
  1166. selector.event.text_position = (bareword ?: syntax_error)->position();
  1167. auto it = selector.event.text.begin();
  1168. bool is_negative = false;
  1169. if (*it == '-') {
  1170. ++it;
  1171. is_negative = true;
  1172. }
  1173. if (it != selector.event.text.end() && AK::all_of(it, selector.event.text.end(), is_digit)) {
  1174. if (is_negative)
  1175. selector.event.kind = AST::HistorySelector::EventKind::IndexFromEnd;
  1176. else
  1177. selector.event.kind = AST::HistorySelector::EventKind::IndexFromStart;
  1178. selector.event.index = abs(selector.event.text.to_int().value());
  1179. }
  1180. break;
  1181. }
  1182. }
  1183. if (peek() != ':')
  1184. return create<AST::HistoryEvent>(move(selector));
  1185. consume();
  1186. // Word selectors
  1187. auto parse_word_selector = [&]() -> Optional<AST::HistorySelector::WordSelector> {
  1188. auto rule_start = push_start();
  1189. auto c = peek();
  1190. if (isdigit(c)) {
  1191. auto num = consume_while(is_digit);
  1192. auto value = num.to_uint();
  1193. return AST::HistorySelector::WordSelector {
  1194. AST::HistorySelector::WordSelectorKind::Index,
  1195. value.value(),
  1196. { m_rule_start_offsets.last(), m_offset, m_rule_start_lines.last(), line() }
  1197. };
  1198. }
  1199. if (c == '^') {
  1200. consume();
  1201. return AST::HistorySelector::WordSelector {
  1202. AST::HistorySelector::WordSelectorKind::Index,
  1203. 0,
  1204. { m_rule_start_offsets.last(), m_offset, m_rule_start_lines.last(), line() }
  1205. };
  1206. }
  1207. if (c == '$') {
  1208. consume();
  1209. return AST::HistorySelector::WordSelector {
  1210. AST::HistorySelector::WordSelectorKind::Last,
  1211. 0,
  1212. { m_rule_start_offsets.last(), m_offset, m_rule_start_lines.last(), line() }
  1213. };
  1214. }
  1215. return {};
  1216. };
  1217. auto start = parse_word_selector();
  1218. if (!start.has_value()) {
  1219. syntax_error = create<AST::SyntaxError>("Expected a word selector after ':' in a history event designator", true);
  1220. auto node = create<AST::HistoryEvent>(move(selector));
  1221. node->set_is_syntax_error(syntax_error->syntax_error_node());
  1222. return node;
  1223. }
  1224. selector.word_selector_range.start = start.release_value();
  1225. if (peek() == '-') {
  1226. consume();
  1227. auto end = parse_word_selector();
  1228. if (!end.has_value()) {
  1229. syntax_error = create<AST::SyntaxError>("Expected a word selector after '-' in a history event designator word selector", true);
  1230. auto node = create<AST::HistoryEvent>(move(selector));
  1231. node->set_is_syntax_error(syntax_error->syntax_error_node());
  1232. return node;
  1233. }
  1234. selector.word_selector_range.end = move(end);
  1235. } else {
  1236. selector.word_selector_range.end.clear();
  1237. }
  1238. return create<AST::HistoryEvent>(move(selector));
  1239. }
  1240. RefPtr<AST::Node> Parser::parse_comment()
  1241. {
  1242. if (at_end())
  1243. return nullptr;
  1244. if (peek() != '#')
  1245. return nullptr;
  1246. consume();
  1247. auto text = consume_while(is_not('\n'));
  1248. return create<AST::Comment>(move(text)); // Comment
  1249. }
  1250. RefPtr<AST::Node> Parser::parse_bareword()
  1251. {
  1252. auto rule_start = push_start();
  1253. StringBuilder builder;
  1254. auto is_acceptable_bareword_character = [&](char c) {
  1255. return strchr("\\\"'*$&#|(){} ?;<>\n", c) == nullptr
  1256. && !m_extra_chars_not_allowed_in_barewords.contains_slow(c);
  1257. };
  1258. while (!at_end()) {
  1259. char ch = peek();
  1260. if (ch == '\\') {
  1261. consume();
  1262. if (!at_end()) {
  1263. ch = consume();
  1264. if (is_acceptable_bareword_character(ch))
  1265. builder.append('\\');
  1266. }
  1267. builder.append(ch);
  1268. continue;
  1269. }
  1270. if (m_is_in_brace_expansion_spec && next_is("..")) {
  1271. // Don't eat '..' in a brace expansion spec.
  1272. break;
  1273. }
  1274. if (is_acceptable_bareword_character(ch)) {
  1275. builder.append(consume());
  1276. continue;
  1277. }
  1278. break;
  1279. }
  1280. if (builder.is_empty())
  1281. return nullptr;
  1282. auto current_end = m_offset;
  1283. auto current_line = line();
  1284. auto string = builder.to_string();
  1285. if (string.starts_with('~')) {
  1286. String username;
  1287. RefPtr<AST::Node> tilde, text;
  1288. auto first_slash_index = string.index_of("/");
  1289. if (first_slash_index.has_value()) {
  1290. username = string.substring_view(1, first_slash_index.value() - 1);
  1291. string = string.substring_view(first_slash_index.value(), string.length() - first_slash_index.value());
  1292. } else {
  1293. username = string.substring_view(1, string.length() - 1);
  1294. string = "";
  1295. }
  1296. // Synthesize a Tilde Node with the correct positioning information.
  1297. {
  1298. restore_to(rule_start->offset, rule_start->line);
  1299. auto ch = consume();
  1300. ASSERT(ch == '~');
  1301. tilde = create<AST::Tilde>(move(username));
  1302. }
  1303. if (string.is_empty())
  1304. return tilde;
  1305. // Synthesize a BarewordLiteral Node with the correct positioning information.
  1306. {
  1307. auto text_start = push_start();
  1308. restore_to(current_end, current_line);
  1309. text = create<AST::BarewordLiteral>(move(string));
  1310. }
  1311. return create<AST::Juxtaposition>(tilde.release_nonnull(), text.release_nonnull()); // Juxtaposition Variable Bareword
  1312. }
  1313. if (string.starts_with("\\~")) {
  1314. // Un-escape the tilde, but only at the start (where it would be an expansion)
  1315. string = string.substring(1, string.length() - 1);
  1316. }
  1317. return create<AST::BarewordLiteral>(move(string)); // Bareword Literal
  1318. }
  1319. RefPtr<AST::Node> Parser::parse_glob()
  1320. {
  1321. auto rule_start = push_start();
  1322. auto bareword_part = parse_bareword();
  1323. if (at_end())
  1324. return bareword_part;
  1325. char ch = peek();
  1326. if (ch == '*' || ch == '?') {
  1327. auto saved_offset = save_offset();
  1328. consume();
  1329. StringBuilder textbuilder;
  1330. if (bareword_part) {
  1331. StringView text;
  1332. if (bareword_part->is_bareword()) {
  1333. auto bareword = static_cast<AST::BarewordLiteral*>(bareword_part.ptr());
  1334. text = bareword->text();
  1335. } else {
  1336. // FIXME: Allow composition of tilde+bareword with globs: '~/foo/bar/baz*'
  1337. restore_to(saved_offset.offset, saved_offset.line);
  1338. bareword_part->set_is_syntax_error(*create<AST::SyntaxError>(String::format("Unexpected %s inside a glob", bareword_part->class_name().characters())));
  1339. return bareword_part;
  1340. }
  1341. textbuilder.append(text);
  1342. }
  1343. textbuilder.append(ch);
  1344. auto glob_after = parse_glob();
  1345. if (glob_after) {
  1346. if (glob_after->is_glob()) {
  1347. auto glob = static_cast<AST::Glob*>(glob_after.ptr());
  1348. textbuilder.append(glob->text());
  1349. } else if (glob_after->is_bareword()) {
  1350. auto bareword = static_cast<AST::BarewordLiteral*>(glob_after.ptr());
  1351. textbuilder.append(bareword->text());
  1352. } else if (glob_after->is_tilde()) {
  1353. auto bareword = static_cast<AST::Tilde*>(glob_after.ptr());
  1354. textbuilder.append("~");
  1355. textbuilder.append(bareword->text());
  1356. } else {
  1357. return create<AST::SyntaxError>(String::formatted("Invalid node '{}' in glob position, escape shell special characters", glob_after->class_name()));
  1358. }
  1359. }
  1360. return create<AST::Glob>(textbuilder.to_string()); // Glob
  1361. }
  1362. return bareword_part;
  1363. }
  1364. RefPtr<AST::Node> Parser::parse_brace_expansion()
  1365. {
  1366. auto rule_start = push_start();
  1367. if (!expect('{'))
  1368. return nullptr;
  1369. if (auto spec = parse_brace_expansion_spec()) {
  1370. if (!expect('}'))
  1371. spec->set_is_syntax_error(create<AST::SyntaxError>("Expected a close brace '}' to end a brace expansion", true));
  1372. return spec;
  1373. }
  1374. restore_to(*rule_start);
  1375. return nullptr;
  1376. }
  1377. RefPtr<AST::Node> Parser::parse_brace_expansion_spec()
  1378. {
  1379. TemporaryChange is_in_brace_expansion { m_is_in_brace_expansion_spec, true };
  1380. TemporaryChange chars_change { m_extra_chars_not_allowed_in_barewords, { ',' } };
  1381. auto rule_start = push_start();
  1382. auto start_expr = parse_expression();
  1383. if (start_expr) {
  1384. if (expect("..")) {
  1385. if (auto end_expr = parse_expression()) {
  1386. if (end_expr->position().start_offset != start_expr->position().end_offset + 2)
  1387. end_expr->set_is_syntax_error(create<AST::SyntaxError>("Expected no whitespace between '..' and the following expression in brace expansion"));
  1388. return create<AST::Range>(start_expr.release_nonnull(), end_expr.release_nonnull());
  1389. }
  1390. return create<AST::Range>(start_expr.release_nonnull(), create<AST::SyntaxError>("Expected an expression to end range brace expansion with", true));
  1391. }
  1392. }
  1393. NonnullRefPtrVector<AST::Node> subexpressions;
  1394. if (start_expr)
  1395. subexpressions.append(start_expr.release_nonnull());
  1396. while (expect(',')) {
  1397. auto expr = parse_expression();
  1398. if (expr) {
  1399. subexpressions.append(expr.release_nonnull());
  1400. } else {
  1401. subexpressions.append(create<AST::StringLiteral>(""));
  1402. }
  1403. }
  1404. if (subexpressions.is_empty())
  1405. return nullptr;
  1406. return create<AST::BraceExpansion>(move(subexpressions));
  1407. }
  1408. StringView Parser::consume_while(Function<bool(char)> condition)
  1409. {
  1410. if (at_end())
  1411. return {};
  1412. auto start_offset = m_offset;
  1413. while (!at_end() && condition(peek()))
  1414. consume();
  1415. return m_input.substring_view(start_offset, m_offset - start_offset);
  1416. }
  1417. bool Parser::next_is(const StringView& next)
  1418. {
  1419. auto start = push_start();
  1420. auto res = expect(next);
  1421. restore_to(*start);
  1422. return res;
  1423. }
  1424. }