Parser.cpp 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743
  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::SyntaxError> 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::WordSelector {
  1144. AST::HistorySelector::WordSelectorKind::Index,
  1145. 0,
  1146. { m_offset, m_offset, m_line, m_line },
  1147. nullptr },
  1148. AST::HistorySelector::WordSelector {
  1149. AST::HistorySelector::WordSelectorKind::Last,
  1150. 0,
  1151. { m_offset, m_offset, m_line, m_line },
  1152. nullptr }
  1153. };
  1154. switch (peek()) {
  1155. case '!':
  1156. consume();
  1157. selector.event.kind = AST::HistorySelector::EventKind::IndexFromEnd;
  1158. selector.event.index = 0;
  1159. selector.event.text = "!";
  1160. break;
  1161. case '?':
  1162. consume();
  1163. selector.event.kind = AST::HistorySelector::EventKind::ContainingStringLookup;
  1164. [[fallthrough]];
  1165. default: {
  1166. TemporaryChange chars_change { m_extra_chars_not_allowed_in_barewords, { ':' } };
  1167. auto bareword = parse_bareword();
  1168. if (!bareword || !bareword->is_bareword()) {
  1169. restore_to(*rule_start);
  1170. return nullptr;
  1171. }
  1172. selector.event.text = static_ptr_cast<AST::BarewordLiteral>(bareword)->text();
  1173. selector.event.text_position = bareword->position();
  1174. auto it = selector.event.text.begin();
  1175. bool is_negative = false;
  1176. if (*it == '-') {
  1177. ++it;
  1178. is_negative = true;
  1179. }
  1180. if (it != selector.event.text.end() && AK::all_of(it, selector.event.text.end(), is_digit)) {
  1181. if (is_negative)
  1182. selector.event.kind = AST::HistorySelector::EventKind::IndexFromEnd;
  1183. else
  1184. selector.event.kind = AST::HistorySelector::EventKind::IndexFromStart;
  1185. auto number = selector.event.text.to_int();
  1186. if (number.has_value())
  1187. selector.event.index = abs(number.value());
  1188. else
  1189. syntax_error = create<AST::SyntaxError>("History entry index value invalid or out of range");
  1190. }
  1191. break;
  1192. }
  1193. }
  1194. if (peek() != ':') {
  1195. auto node = create<AST::HistoryEvent>(move(selector));
  1196. if (syntax_error)
  1197. node->set_is_syntax_error(*syntax_error);
  1198. return node;
  1199. }
  1200. consume();
  1201. // Word selectors
  1202. auto parse_word_selector = [&]() -> Optional<AST::HistorySelector::WordSelector> {
  1203. auto rule_start = push_start();
  1204. auto c = peek();
  1205. if (isdigit(c)) {
  1206. auto num = consume_while(is_digit);
  1207. auto value = num.to_uint();
  1208. if (!value.has_value()) {
  1209. return AST::HistorySelector::WordSelector {
  1210. AST::HistorySelector::WordSelectorKind::Index,
  1211. 0,
  1212. { m_rule_start_offsets.last(), m_offset, m_rule_start_lines.last(), line() },
  1213. syntax_error ? NonnullRefPtr(*syntax_error) : create<AST::SyntaxError>("Word selector value invalid or out of range")
  1214. };
  1215. }
  1216. return AST::HistorySelector::WordSelector {
  1217. AST::HistorySelector::WordSelectorKind::Index,
  1218. value.value(),
  1219. { m_rule_start_offsets.last(), m_offset, m_rule_start_lines.last(), line() },
  1220. syntax_error
  1221. };
  1222. }
  1223. if (c == '^') {
  1224. consume();
  1225. return AST::HistorySelector::WordSelector {
  1226. AST::HistorySelector::WordSelectorKind::Index,
  1227. 0,
  1228. { m_rule_start_offsets.last(), m_offset, m_rule_start_lines.last(), line() },
  1229. syntax_error
  1230. };
  1231. }
  1232. if (c == '$') {
  1233. consume();
  1234. return AST::HistorySelector::WordSelector {
  1235. AST::HistorySelector::WordSelectorKind::Last,
  1236. 0,
  1237. { m_rule_start_offsets.last(), m_offset, m_rule_start_lines.last(), line() },
  1238. syntax_error
  1239. };
  1240. }
  1241. return {};
  1242. };
  1243. auto start = parse_word_selector();
  1244. if (!start.has_value()) {
  1245. if (!syntax_error)
  1246. syntax_error = create<AST::SyntaxError>("Expected a word selector after ':' in a history event designator", true);
  1247. auto node = create<AST::HistoryEvent>(move(selector));
  1248. node->set_is_syntax_error(*syntax_error);
  1249. return node;
  1250. }
  1251. selector.word_selector_range.start = start.release_value();
  1252. if (peek() == '-') {
  1253. consume();
  1254. auto end = parse_word_selector();
  1255. if (!end.has_value()) {
  1256. if (!syntax_error)
  1257. syntax_error = create<AST::SyntaxError>("Expected a word selector after '-' in a history event designator word selector", true);
  1258. auto node = create<AST::HistoryEvent>(move(selector));
  1259. node->set_is_syntax_error(*syntax_error);
  1260. return node;
  1261. }
  1262. selector.word_selector_range.end = move(end);
  1263. } else {
  1264. selector.word_selector_range.end.clear();
  1265. }
  1266. auto node = create<AST::HistoryEvent>(move(selector));
  1267. if (syntax_error)
  1268. node->set_is_syntax_error(*syntax_error);
  1269. return node;
  1270. }
  1271. RefPtr<AST::Node> Parser::parse_comment()
  1272. {
  1273. if (at_end())
  1274. return nullptr;
  1275. if (peek() != '#')
  1276. return nullptr;
  1277. consume();
  1278. auto text = consume_while(is_not('\n'));
  1279. return create<AST::Comment>(move(text)); // Comment
  1280. }
  1281. RefPtr<AST::Node> Parser::parse_bareword()
  1282. {
  1283. auto rule_start = push_start();
  1284. StringBuilder builder;
  1285. auto is_acceptable_bareword_character = [&](char c) {
  1286. return strchr("\\\"'*$&#|(){} ?;<>\n", c) == nullptr
  1287. && !m_extra_chars_not_allowed_in_barewords.contains_slow(c);
  1288. };
  1289. while (!at_end()) {
  1290. char ch = peek();
  1291. if (ch == '\\') {
  1292. consume();
  1293. if (!at_end()) {
  1294. ch = consume();
  1295. if (is_acceptable_bareword_character(ch))
  1296. builder.append('\\');
  1297. }
  1298. builder.append(ch);
  1299. continue;
  1300. }
  1301. if (m_is_in_brace_expansion_spec && next_is("..")) {
  1302. // Don't eat '..' in a brace expansion spec.
  1303. break;
  1304. }
  1305. if (is_acceptable_bareword_character(ch)) {
  1306. builder.append(consume());
  1307. continue;
  1308. }
  1309. break;
  1310. }
  1311. if (builder.is_empty())
  1312. return nullptr;
  1313. auto current_end = m_offset;
  1314. auto current_line = line();
  1315. auto string = builder.to_string();
  1316. if (string.starts_with('~')) {
  1317. String username;
  1318. RefPtr<AST::Node> tilde, text;
  1319. auto first_slash_index = string.index_of("/");
  1320. if (first_slash_index.has_value()) {
  1321. username = string.substring_view(1, first_slash_index.value() - 1);
  1322. string = string.substring_view(first_slash_index.value(), string.length() - first_slash_index.value());
  1323. } else {
  1324. username = string.substring_view(1, string.length() - 1);
  1325. string = "";
  1326. }
  1327. // Synthesize a Tilde Node with the correct positioning information.
  1328. {
  1329. restore_to(rule_start->offset, rule_start->line);
  1330. auto ch = consume();
  1331. ASSERT(ch == '~');
  1332. tilde = create<AST::Tilde>(move(username));
  1333. }
  1334. if (string.is_empty())
  1335. return tilde;
  1336. // Synthesize a BarewordLiteral Node with the correct positioning information.
  1337. {
  1338. auto text_start = push_start();
  1339. restore_to(current_end, current_line);
  1340. text = create<AST::BarewordLiteral>(move(string));
  1341. }
  1342. return create<AST::Juxtaposition>(tilde.release_nonnull(), text.release_nonnull()); // Juxtaposition Variable Bareword
  1343. }
  1344. if (string.starts_with("\\~")) {
  1345. // Un-escape the tilde, but only at the start (where it would be an expansion)
  1346. string = string.substring(1, string.length() - 1);
  1347. }
  1348. return create<AST::BarewordLiteral>(move(string)); // Bareword Literal
  1349. }
  1350. RefPtr<AST::Node> Parser::parse_glob()
  1351. {
  1352. auto rule_start = push_start();
  1353. auto bareword_part = parse_bareword();
  1354. if (at_end())
  1355. return bareword_part;
  1356. char ch = peek();
  1357. if (ch == '*' || ch == '?') {
  1358. auto saved_offset = save_offset();
  1359. consume();
  1360. StringBuilder textbuilder;
  1361. if (bareword_part) {
  1362. StringView text;
  1363. if (bareword_part->is_bareword()) {
  1364. auto bareword = static_cast<AST::BarewordLiteral*>(bareword_part.ptr());
  1365. text = bareword->text();
  1366. } else {
  1367. // FIXME: Allow composition of tilde+bareword with globs: '~/foo/bar/baz*'
  1368. restore_to(saved_offset.offset, saved_offset.line);
  1369. bareword_part->set_is_syntax_error(*create<AST::SyntaxError>(String::format("Unexpected %s inside a glob", bareword_part->class_name().characters())));
  1370. return bareword_part;
  1371. }
  1372. textbuilder.append(text);
  1373. }
  1374. textbuilder.append(ch);
  1375. auto glob_after = parse_glob();
  1376. if (glob_after) {
  1377. if (glob_after->is_glob()) {
  1378. auto glob = static_cast<AST::Glob*>(glob_after.ptr());
  1379. textbuilder.append(glob->text());
  1380. } else if (glob_after->is_bareword()) {
  1381. auto bareword = static_cast<AST::BarewordLiteral*>(glob_after.ptr());
  1382. textbuilder.append(bareword->text());
  1383. } else if (glob_after->is_tilde()) {
  1384. auto bareword = static_cast<AST::Tilde*>(glob_after.ptr());
  1385. textbuilder.append("~");
  1386. textbuilder.append(bareword->text());
  1387. } else {
  1388. return create<AST::SyntaxError>(String::formatted("Invalid node '{}' in glob position, escape shell special characters", glob_after->class_name()));
  1389. }
  1390. }
  1391. return create<AST::Glob>(textbuilder.to_string()); // Glob
  1392. }
  1393. return bareword_part;
  1394. }
  1395. RefPtr<AST::Node> Parser::parse_brace_expansion()
  1396. {
  1397. auto rule_start = push_start();
  1398. if (!expect('{'))
  1399. return nullptr;
  1400. if (auto spec = parse_brace_expansion_spec()) {
  1401. if (!expect('}'))
  1402. spec->set_is_syntax_error(create<AST::SyntaxError>("Expected a close brace '}' to end a brace expansion", true));
  1403. return spec;
  1404. }
  1405. restore_to(*rule_start);
  1406. return nullptr;
  1407. }
  1408. RefPtr<AST::Node> Parser::parse_brace_expansion_spec()
  1409. {
  1410. TemporaryChange is_in_brace_expansion { m_is_in_brace_expansion_spec, true };
  1411. TemporaryChange chars_change { m_extra_chars_not_allowed_in_barewords, { ',' } };
  1412. auto rule_start = push_start();
  1413. auto start_expr = parse_expression();
  1414. if (start_expr) {
  1415. if (expect("..")) {
  1416. if (auto end_expr = parse_expression()) {
  1417. if (end_expr->position().start_offset != start_expr->position().end_offset + 2)
  1418. end_expr->set_is_syntax_error(create<AST::SyntaxError>("Expected no whitespace between '..' and the following expression in brace expansion"));
  1419. return create<AST::Range>(start_expr.release_nonnull(), end_expr.release_nonnull());
  1420. }
  1421. return create<AST::Range>(start_expr.release_nonnull(), create<AST::SyntaxError>("Expected an expression to end range brace expansion with", true));
  1422. }
  1423. }
  1424. NonnullRefPtrVector<AST::Node> subexpressions;
  1425. if (start_expr)
  1426. subexpressions.append(start_expr.release_nonnull());
  1427. while (expect(',')) {
  1428. auto expr = parse_expression();
  1429. if (expr) {
  1430. subexpressions.append(expr.release_nonnull());
  1431. } else {
  1432. subexpressions.append(create<AST::StringLiteral>(""));
  1433. }
  1434. }
  1435. if (subexpressions.is_empty())
  1436. return nullptr;
  1437. return create<AST::BraceExpansion>(move(subexpressions));
  1438. }
  1439. StringView Parser::consume_while(Function<bool(char)> condition)
  1440. {
  1441. if (at_end())
  1442. return {};
  1443. auto start_offset = m_offset;
  1444. while (!at_end() && condition(peek()))
  1445. consume();
  1446. return m_input.substring_view(start_offset, m_offset - start_offset);
  1447. }
  1448. bool Parser::next_is(const StringView& next)
  1449. {
  1450. auto start = push_start();
  1451. auto res = expect(next);
  1452. restore_to(*start);
  1453. return res;
  1454. }
  1455. }