PosixParser.cpp 65 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922
  1. /*
  2. * Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/CharacterTypes.h>
  7. #include <AK/Debug.h>
  8. #include <AK/StringUtils.h>
  9. #include <Shell/PosixParser.h>
  10. template<typename T, typename... Ts>
  11. static inline bool is_one_of(T const& value, Ts const&... values)
  12. {
  13. return ((value == values) || ...);
  14. }
  15. static inline bool is_io_operator(Shell::Posix::Token const& token)
  16. {
  17. using namespace Shell::Posix;
  18. return is_one_of(token.type,
  19. Token::Type::Less, Token::Type::Great,
  20. Token::Type::LessAnd, Token::Type::GreatAnd,
  21. Token::Type::DoubleLess, Token::Type::DoubleGreat,
  22. Token::Type::LessGreat, Token::Type::Clobber);
  23. }
  24. static inline bool is_separator(Shell::Posix::Token const& token)
  25. {
  26. using namespace Shell::Posix;
  27. return is_one_of(token.type,
  28. Token::Type::Semicolon, Token::Type::Newline,
  29. Token::Type::AndIf, Token::Type::OrIf,
  30. Token::Type::Pipe,
  31. Token::Type::And);
  32. }
  33. static inline bool is_a_reserved_word_position(Shell::Posix::Token const& token, Optional<Shell::Posix::Token> const& previous_token, Optional<Shell::Posix::Token> const& previous_previous_token)
  34. {
  35. using namespace Shell::Posix;
  36. auto is_start_of_command = !previous_token.has_value()
  37. || previous_token->value.is_empty()
  38. || is_separator(*previous_token)
  39. || is_one_of(previous_token->type,
  40. Token::Type::OpenParen, Token::Type::CloseParen, Token::Type::Newline, Token::Type::DoubleSemicolon,
  41. Token::Type::Semicolon, Token::Type::Pipe, Token::Type::OrIf, Token::Type::AndIf);
  42. if (is_start_of_command)
  43. return true;
  44. if (!previous_token.has_value())
  45. return false;
  46. auto previous_is_reserved_word = is_one_of(previous_token->value,
  47. "for"sv, "in"sv, "case"sv, "if"sv, "then"sv, "else"sv,
  48. "elif"sv, "while"sv, "until"sv, "do"sv, "done"sv, "esac"sv,
  49. "fi"sv, "!"sv, "{"sv, "}"sv);
  50. if (previous_is_reserved_word)
  51. return true;
  52. if (!previous_previous_token.has_value())
  53. return false;
  54. auto is_third_in_case = previous_previous_token->value == "case"sv
  55. && token.type == Token::Type::Token && token.value == "in"sv;
  56. if (is_third_in_case)
  57. return true;
  58. auto is_third_in_for = previous_previous_token->value == "for"sv
  59. && token.type == Token::Type::Token && is_one_of(token.value, "in"sv, "do"sv);
  60. return is_third_in_for;
  61. }
  62. static inline bool is_reserved(Shell::Posix::Token const& token)
  63. {
  64. using namespace Shell::Posix;
  65. return is_one_of(token.type,
  66. Token::Type::If, Token::Type::Then, Token::Type::Else,
  67. Token::Type::Elif, Token::Type::Fi, Token::Type::Do,
  68. Token::Type::Done, Token::Type::Case, Token::Type::Esac,
  69. Token::Type::While, Token::Type::Until, Token::Type::For,
  70. Token::Type::In, Token::Type::OpenBrace, Token::Type::CloseBrace,
  71. Token::Type::Bang);
  72. }
  73. static inline bool is_valid_name(StringView word)
  74. {
  75. // Dr.POSIX: a word consisting solely of underscores, digits, and alphabetics from the portable character set. The first character of a name is not a digit.
  76. return !word.is_empty()
  77. && !is_ascii_digit(word[0])
  78. && all_of(word, [](auto ch) { return is_ascii_alphanumeric(ch) || ch == '_'; });
  79. }
  80. namespace Shell::Posix {
  81. void Parser::fill_token_buffer()
  82. {
  83. for (;;) {
  84. auto token = next_expanded_token();
  85. if (!token.has_value())
  86. break;
  87. #if SHELL_POSIX_PARSER_DEBUG
  88. DeprecatedString position = "(~)";
  89. if (token->position.has_value())
  90. position = DeprecatedString::formatted("{}:{}", token->position->start_offset, token->position->end_offset);
  91. DeprecatedString expansions = "";
  92. for (auto& exp : token->resolved_expansions)
  93. exp.visit(
  94. [&](ResolvedParameterExpansion& x) { expansions = DeprecatedString::formatted("{}param({}),", expansions, x.to_deprecated_string()); },
  95. [&](ResolvedCommandExpansion& x) { expansions = DeprecatedString::formatted("{}command({:p})", expansions, x.command.ptr()); });
  96. DeprecatedString rexpansions = "";
  97. for (auto& exp : token->expansions)
  98. exp.visit(
  99. [&](ParameterExpansion& x) { rexpansions = DeprecatedString::formatted("{}param({}) from {} to {},", rexpansions, x.parameter.string_view(), x.range.start, x.range.length); },
  100. [&](auto&) { rexpansions = DeprecatedString::formatted("{}...,", rexpansions); });
  101. dbgln("Token @ {}: '{}' (type {}) - parsed expansions: {} - raw expansions: {}", position, token->value.replace("\n"sv, "\\n"sv, ReplaceMode::All), token->type_name(), expansions, rexpansions);
  102. #endif
  103. }
  104. m_token_index = 0;
  105. }
  106. RefPtr<AST::Node> Parser::parse()
  107. {
  108. return parse_complete_command();
  109. }
  110. Optional<Token> Parser::next_expanded_token()
  111. {
  112. while (m_token_buffer.find_if([](auto& token) { return token.type == Token::Type::Eof; }).is_end()) {
  113. auto tokens = m_lexer.batch_next();
  114. auto expanded = perform_expansions(move(tokens));
  115. m_token_buffer.extend(expanded);
  116. }
  117. if (m_token_buffer.size() == m_token_index)
  118. return {};
  119. return m_token_buffer[m_token_index++];
  120. }
  121. Vector<Token> Parser::perform_expansions(Vector<Token> tokens)
  122. {
  123. if (tokens.is_empty())
  124. return {};
  125. Vector<Token> expanded_tokens;
  126. auto previous_token = Optional<Token>();
  127. auto previous_previous_token = Optional<Token>();
  128. auto tokens_taken_from_buffer = 0;
  129. expanded_tokens.ensure_capacity(tokens.size());
  130. auto swap_expansions = [&] {
  131. if (previous_previous_token.has_value())
  132. expanded_tokens.append(previous_previous_token.release_value());
  133. if (previous_token.has_value())
  134. expanded_tokens.append(previous_token.release_value());
  135. for (; tokens_taken_from_buffer > 0; tokens_taken_from_buffer--)
  136. m_token_buffer.append(expanded_tokens.take_first());
  137. swap(tokens, expanded_tokens);
  138. expanded_tokens.clear_with_capacity();
  139. };
  140. // (1) join all consecutive newlines (this works around a grammar ambiguity)
  141. auto previous_was_newline = !m_token_buffer.is_empty() && m_token_buffer.last().type == Token::Type::Newline;
  142. for (auto& token : tokens) {
  143. if (token.type == Token::Type::Newline) {
  144. if (previous_was_newline)
  145. continue;
  146. previous_was_newline = true;
  147. } else {
  148. previous_was_newline = false;
  149. }
  150. expanded_tokens.append(move(token));
  151. }
  152. swap_expansions();
  153. // (2) Detect reserved words
  154. if (m_token_buffer.size() >= 1) {
  155. previous_token = m_token_buffer.take_last();
  156. tokens_taken_from_buffer++;
  157. }
  158. if (m_token_buffer.size() >= 1) {
  159. previous_previous_token = m_token_buffer.take_last();
  160. tokens_taken_from_buffer++;
  161. }
  162. auto check_reserved_word = [&](auto& token) {
  163. if (is_a_reserved_word_position(token, previous_token, previous_previous_token)) {
  164. if (token.value == "if"sv)
  165. token.type = Token::Type::If;
  166. else if (token.value == "then"sv)
  167. token.type = Token::Type::Then;
  168. else if (token.value == "else"sv)
  169. token.type = Token::Type::Else;
  170. else if (token.value == "elif"sv)
  171. token.type = Token::Type::Elif;
  172. else if (token.value == "fi"sv)
  173. token.type = Token::Type::Fi;
  174. else if (token.value == "while"sv)
  175. token.type = Token::Type::While;
  176. else if (token.value == "until"sv)
  177. token.type = Token::Type::Until;
  178. else if (token.value == "do"sv)
  179. token.type = Token::Type::Do;
  180. else if (token.value == "done"sv)
  181. token.type = Token::Type::Done;
  182. else if (token.value == "case"sv)
  183. token.type = Token::Type::Case;
  184. else if (token.value == "esac"sv)
  185. token.type = Token::Type::Esac;
  186. else if (token.value == "for"sv)
  187. token.type = Token::Type::For;
  188. else if (token.value == "in"sv)
  189. token.type = Token::Type::In;
  190. else if (token.value == "!"sv)
  191. token.type = Token::Type::Bang;
  192. else if (token.value == "{"sv)
  193. token.type = Token::Type::OpenBrace;
  194. else if (token.value == "}"sv)
  195. token.type = Token::Type::CloseBrace;
  196. else if (token.type == Token::Type::Token)
  197. token.type = Token::Type::Word;
  198. } else if (token.type == Token::Type::Token) {
  199. token.type = Token::Type::Word;
  200. }
  201. };
  202. for (auto& token : tokens) {
  203. if (!previous_token.has_value()) {
  204. check_reserved_word(token);
  205. previous_token = token;
  206. continue;
  207. }
  208. if (!previous_previous_token.has_value()) {
  209. check_reserved_word(token);
  210. previous_previous_token = move(previous_token);
  211. previous_token = token;
  212. continue;
  213. }
  214. check_reserved_word(token);
  215. expanded_tokens.append(exchange(*previous_previous_token, exchange(*previous_token, move(token))));
  216. }
  217. swap_expansions();
  218. // (3) Detect io_number tokens
  219. previous_token = Optional<Token>();
  220. tokens_taken_from_buffer = 0;
  221. if (m_token_buffer.size() >= 1) {
  222. previous_token = m_token_buffer.take_last();
  223. tokens_taken_from_buffer++;
  224. }
  225. for (auto& token : tokens) {
  226. if (!previous_token.has_value()) {
  227. previous_token = token;
  228. continue;
  229. }
  230. if (is_io_operator(token) && previous_token->type == Token::Type::Word && all_of(previous_token->value, is_ascii_digit)) {
  231. previous_token->type = Token::Type::IoNumber;
  232. }
  233. expanded_tokens.append(exchange(*previous_token, move(token)));
  234. }
  235. swap_expansions();
  236. // (4) Try to identify simple commands
  237. previous_token = Optional<Token>();
  238. tokens_taken_from_buffer = 0;
  239. if (m_token_buffer.size() >= 1) {
  240. previous_token = m_token_buffer.take_last();
  241. tokens_taken_from_buffer++;
  242. }
  243. for (auto& token : tokens) {
  244. if (!previous_token.has_value()) {
  245. token.could_be_start_of_a_simple_command = true;
  246. previous_token = token;
  247. continue;
  248. }
  249. token.could_be_start_of_a_simple_command = is_one_of(previous_token->type, Token::Type::OpenParen, Token::Type::CloseParen, Token::Type::Newline)
  250. || is_separator(*previous_token)
  251. || (!is_reserved(*previous_token) && is_reserved(token));
  252. expanded_tokens.append(exchange(*previous_token, move(token)));
  253. }
  254. swap_expansions();
  255. // (5) Detect assignment words
  256. for (auto& token : tokens) {
  257. if (token.could_be_start_of_a_simple_command)
  258. m_disallow_command_prefix = false;
  259. // Check if we're in a command prefix (could be an assignment)
  260. if (!m_disallow_command_prefix && token.type == Token::Type::Word && token.value.contains('=')) {
  261. // If the word before '=' is a valid name, this is an assignment
  262. auto parts = token.value.split_limit('=', 2);
  263. if (is_valid_name(parts[0]))
  264. token.type = Token::Type::AssignmentWord;
  265. else
  266. m_disallow_command_prefix = true;
  267. } else {
  268. m_disallow_command_prefix = true;
  269. }
  270. expanded_tokens.append(move(token));
  271. }
  272. swap_expansions();
  273. // (6) Parse expansions
  274. for (auto& token : tokens) {
  275. if (!is_one_of(token.type, Token::Type::Word, Token::Type::AssignmentWord)) {
  276. expanded_tokens.append(move(token));
  277. continue;
  278. }
  279. Vector<ResolvedExpansion> resolved_expansions;
  280. for (auto& expansion : token.expansions) {
  281. auto resolved = expansion.visit(
  282. [&](ParameterExpansion const& expansion) -> ResolvedExpansion {
  283. auto text = expansion.parameter.string_view();
  284. // ${NUMBER}
  285. if (all_of(text, is_ascii_digit)) {
  286. return ResolvedParameterExpansion {
  287. .parameter = expansion.parameter.to_deprecated_string(),
  288. .argument = {},
  289. .range = expansion.range,
  290. .op = ResolvedParameterExpansion::Op::GetPositionalParameter,
  291. };
  292. }
  293. if (text.length() == 1) {
  294. ResolvedParameterExpansion::Op op;
  295. switch (text[0]) {
  296. case '!':
  297. op = ResolvedParameterExpansion::Op::GetLastBackgroundPid;
  298. break;
  299. case '@':
  300. op = ResolvedParameterExpansion::Op::GetPositionalParameterList;
  301. break;
  302. case '-':
  303. op = ResolvedParameterExpansion::Op::GetCurrentOptionFlags;
  304. break;
  305. case '#':
  306. op = ResolvedParameterExpansion::Op::GetPositionalParameterCount;
  307. break;
  308. case '?':
  309. op = ResolvedParameterExpansion::Op::GetLastExitStatus;
  310. break;
  311. case '*':
  312. op = ResolvedParameterExpansion::Op::GetPositionalParameterListAsString;
  313. break;
  314. case '$':
  315. op = ResolvedParameterExpansion::Op::GetShellProcessId;
  316. break;
  317. default:
  318. if (is_valid_name(text)) {
  319. op = ResolvedParameterExpansion::Op::GetVariable;
  320. } else {
  321. error(token, "Unknown parameter expansion: {}", text);
  322. return ResolvedParameterExpansion {
  323. .parameter = expansion.parameter.to_deprecated_string(),
  324. .argument = {},
  325. .range = expansion.range,
  326. .op = ResolvedParameterExpansion::Op::StringLength,
  327. };
  328. }
  329. }
  330. return ResolvedParameterExpansion {
  331. .parameter = {},
  332. .argument = {},
  333. .range = expansion.range,
  334. .op = op,
  335. };
  336. }
  337. if (text.starts_with('#')) {
  338. return ResolvedParameterExpansion {
  339. .parameter = text.substring_view(1).to_deprecated_string(),
  340. .argument = {},
  341. .range = expansion.range,
  342. .op = ResolvedParameterExpansion::Op::StringLength,
  343. };
  344. }
  345. GenericLexer lexer { text };
  346. auto parameter = lexer.consume_while([first = true](char c) mutable {
  347. if (first) {
  348. first = false;
  349. return is_ascii_alpha(c) || c == '_';
  350. }
  351. return is_ascii_alphanumeric(c) || c == '_';
  352. });
  353. StringView argument;
  354. ResolvedParameterExpansion::Op op;
  355. switch (lexer.peek()) {
  356. case ':':
  357. lexer.ignore();
  358. switch (lexer.is_eof() ? 0 : lexer.consume()) {
  359. case '-':
  360. argument = lexer.consume_all();
  361. op = ResolvedParameterExpansion::Op::UseDefaultValue;
  362. break;
  363. case '=':
  364. argument = lexer.consume_all();
  365. op = ResolvedParameterExpansion::Op::AssignDefaultValue;
  366. break;
  367. case '?':
  368. argument = lexer.consume_all();
  369. op = ResolvedParameterExpansion::Op::IndicateErrorIfEmpty;
  370. break;
  371. case '+':
  372. argument = lexer.consume_all();
  373. op = ResolvedParameterExpansion::Op::UseAlternativeValue;
  374. break;
  375. default:
  376. error(token, "Unknown parameter expansion: {}", text);
  377. return ResolvedParameterExpansion {
  378. .parameter = parameter.to_deprecated_string(),
  379. .argument = {},
  380. .range = expansion.range,
  381. .op = ResolvedParameterExpansion::Op::StringLength,
  382. };
  383. }
  384. break;
  385. case '-':
  386. lexer.ignore();
  387. argument = lexer.consume_all();
  388. op = ResolvedParameterExpansion::Op::UseDefaultValueIfUnset;
  389. break;
  390. case '=':
  391. lexer.ignore();
  392. argument = lexer.consume_all();
  393. op = ResolvedParameterExpansion::Op::AssignDefaultValueIfUnset;
  394. break;
  395. case '?':
  396. lexer.ignore();
  397. argument = lexer.consume_all();
  398. op = ResolvedParameterExpansion::Op::IndicateErrorIfUnset;
  399. break;
  400. case '+':
  401. lexer.ignore();
  402. argument = lexer.consume_all();
  403. op = ResolvedParameterExpansion::Op::UseAlternativeValueIfUnset;
  404. break;
  405. case '%':
  406. if (lexer.consume_specific('%'))
  407. op = ResolvedParameterExpansion::Op::RemoveLargestSuffixByPattern;
  408. else
  409. op = ResolvedParameterExpansion::Op::RemoveSmallestSuffixByPattern;
  410. argument = lexer.consume_all();
  411. break;
  412. case '#':
  413. if (lexer.consume_specific('#'))
  414. op = ResolvedParameterExpansion::Op::RemoveLargestPrefixByPattern;
  415. else
  416. op = ResolvedParameterExpansion::Op::RemoveSmallestPrefixByPattern;
  417. argument = lexer.consume_all();
  418. break;
  419. default:
  420. if (is_valid_name(text)) {
  421. op = ResolvedParameterExpansion::Op::GetVariable;
  422. } else {
  423. error(token, "Unknown parameter expansion: {}", text);
  424. return ResolvedParameterExpansion {
  425. .parameter = parameter.to_deprecated_string(),
  426. .argument = {},
  427. .range = expansion.range,
  428. .op = ResolvedParameterExpansion::Op::StringLength,
  429. };
  430. }
  431. }
  432. VERIFY(lexer.is_eof());
  433. return ResolvedParameterExpansion {
  434. .parameter = parameter.to_deprecated_string(),
  435. .argument = argument.to_deprecated_string(),
  436. .range = expansion.range,
  437. .op = op,
  438. .expand = ResolvedParameterExpansion::Expand::Word,
  439. };
  440. },
  441. [&](ArithmeticExpansion const& expansion) -> ResolvedExpansion {
  442. error(token, "Arithmetic expansion is not supported");
  443. return ResolvedParameterExpansion {
  444. .parameter = ""sv,
  445. .argument = ""sv,
  446. .range = expansion.range,
  447. .op = ResolvedParameterExpansion::Op::StringLength,
  448. .expand = ResolvedParameterExpansion::Expand::Nothing,
  449. };
  450. },
  451. [&](CommandExpansion const& expansion) -> ResolvedExpansion {
  452. Parser parser { expansion.command.string_view() };
  453. auto node = parser.parse();
  454. m_errors.extend(move(parser.m_errors));
  455. return ResolvedCommandExpansion {
  456. move(node),
  457. expansion.range,
  458. };
  459. });
  460. resolved_expansions.append(move(resolved));
  461. }
  462. token.resolved_expansions = move(resolved_expansions);
  463. expanded_tokens.append(move(token));
  464. }
  465. swap_expansions();
  466. // (7) Loop variables
  467. previous_token = {};
  468. tokens_taken_from_buffer = 0;
  469. if (m_token_buffer.size() >= 1) {
  470. previous_token = m_token_buffer.take_last();
  471. tokens_taken_from_buffer++;
  472. }
  473. for (auto& token : tokens) {
  474. if (!previous_token.has_value()) {
  475. previous_token = token;
  476. continue;
  477. }
  478. if (previous_token->type == Token::Type::For && token.type == Token::Type::Word && is_valid_name(token.value)) {
  479. token.type = Token::Type::VariableName;
  480. }
  481. expanded_tokens.append(exchange(*previous_token, token));
  482. }
  483. swap_expansions();
  484. // (8) Function names
  485. previous_token = {};
  486. previous_previous_token = {};
  487. tokens_taken_from_buffer = 0;
  488. if (m_token_buffer.size() >= 1) {
  489. previous_token = m_token_buffer.take_last();
  490. tokens_taken_from_buffer++;
  491. }
  492. if (m_token_buffer.size() >= 1) {
  493. previous_previous_token = m_token_buffer.take_last();
  494. tokens_taken_from_buffer++;
  495. }
  496. for (auto& token : tokens) {
  497. if (!previous_token.has_value()) {
  498. previous_token = token;
  499. continue;
  500. }
  501. if (!previous_previous_token.has_value()) {
  502. previous_previous_token = move(previous_token);
  503. previous_token = token;
  504. continue;
  505. }
  506. // NAME ( )
  507. if (previous_previous_token->could_be_start_of_a_simple_command
  508. && previous_previous_token->type == Token::Type::Word
  509. && previous_token->type == Token::Type::OpenParen
  510. && token.type == Token::Type::CloseParen) {
  511. previous_previous_token->type = Token::Type::VariableName;
  512. }
  513. expanded_tokens.append(exchange(*previous_previous_token, exchange(*previous_token, token)));
  514. }
  515. swap_expansions();
  516. return tokens;
  517. }
  518. static AST::Position empty_position()
  519. {
  520. return { 0, 0, { 0, 0 }, { 0, 0 } };
  521. }
  522. RefPtr<AST::Node> Parser::parse_complete_command()
  523. {
  524. auto list = [&] {
  525. // separator...
  526. while (is_separator(peek()))
  527. skip();
  528. // list EOF
  529. auto list = parse_list();
  530. if (eof())
  531. return list;
  532. // list separator EOF
  533. while (is_separator(peek()))
  534. skip();
  535. if (eof())
  536. return list;
  537. auto position = peek().position;
  538. auto syntax_error = make_ref_counted<AST::SyntaxError>(
  539. position.value_or(empty_position()),
  540. "Extra tokens after complete command"sv);
  541. if (list)
  542. list->set_is_syntax_error(*syntax_error);
  543. else
  544. list = syntax_error;
  545. return list;
  546. }();
  547. if (!list)
  548. return nullptr;
  549. return make_ref_counted<AST::Execute>(list->position(), *list);
  550. }
  551. RefPtr<AST::Node> Parser::parse_list()
  552. {
  553. NonnullRefPtrVector<AST::Node> nodes;
  554. Vector<AST::Position> positions;
  555. auto start_position = peek().position.value_or(empty_position());
  556. for (;;) {
  557. auto new_node = parse_and_or();
  558. if (!new_node)
  559. break;
  560. if (peek().type == Token::Type::And) {
  561. new_node = make_ref_counted<AST::Background>(
  562. new_node->position(),
  563. *new_node);
  564. }
  565. nodes.append(new_node.release_nonnull());
  566. if (!is_separator(peek()) || eof())
  567. break;
  568. auto position = consume().position;
  569. if (position.has_value())
  570. positions.append(position.release_value());
  571. }
  572. auto end_position = peek().position.value_or(empty_position());
  573. return make_ref_counted<AST::Sequence>(
  574. AST::Position {
  575. start_position.start_offset,
  576. end_position.end_offset,
  577. start_position.start_line,
  578. start_position.end_line,
  579. },
  580. move(nodes),
  581. move(positions));
  582. }
  583. RefPtr<AST::Node> Parser::parse_and_or()
  584. {
  585. auto node = parse_pipeline();
  586. if (!node)
  587. return {};
  588. for (;;) {
  589. if (peek().type == Token::Type::AndIf) {
  590. auto and_token = consume();
  591. while (peek().type == Token::Type::Newline)
  592. skip();
  593. auto rhs = parse_pipeline();
  594. if (!rhs)
  595. return {};
  596. node = make_ref_counted<AST::And>(
  597. node->position(),
  598. *node,
  599. rhs.release_nonnull(),
  600. and_token.position.value_or(empty_position()));
  601. continue;
  602. }
  603. if (peek().type == Token::Type::OrIf) {
  604. auto or_token = consume();
  605. while (peek().type == Token::Type::Newline)
  606. skip();
  607. auto rhs = parse_pipeline();
  608. if (!rhs)
  609. return {};
  610. node = make_ref_counted<AST::And>(
  611. node->position(),
  612. *node,
  613. rhs.release_nonnull(),
  614. or_token.position.value_or(empty_position()));
  615. continue;
  616. }
  617. break;
  618. }
  619. return node;
  620. }
  621. RefPtr<AST::Node> Parser::parse_pipeline()
  622. {
  623. return parse_pipe_sequence();
  624. }
  625. RefPtr<AST::Node> Parser::parse_pipe_sequence()
  626. {
  627. auto node = parse_command();
  628. if (!node)
  629. return {};
  630. for (;;) {
  631. if (peek().type != Token::Type::Pipe)
  632. break;
  633. consume();
  634. while (peek().type == Token::Type::Newline)
  635. skip();
  636. auto rhs = parse_command();
  637. if (!rhs)
  638. return {};
  639. node = make_ref_counted<AST::Pipe>(
  640. node->position(),
  641. *node,
  642. rhs.release_nonnull());
  643. }
  644. return node;
  645. }
  646. RefPtr<AST::Node> Parser::parse_command()
  647. {
  648. auto node = [this] {
  649. if (auto node = parse_function_definition())
  650. return node;
  651. if (auto node = parse_simple_command())
  652. return node;
  653. auto node = parse_compound_command();
  654. if (!node)
  655. return node;
  656. if (auto list = parse_redirect_list()) {
  657. auto position = list->position();
  658. node = make_ref_counted<AST::Join>(
  659. node->position().with_end(position),
  660. *node,
  661. list.release_nonnull());
  662. }
  663. return node;
  664. }();
  665. if (!node)
  666. return nullptr;
  667. return make_ref_counted<AST::CastToCommand>(node->position(), *node);
  668. }
  669. RefPtr<AST::Node> Parser::parse_function_definition()
  670. {
  671. // NAME OPEN_PAREN CLOSE_PAREN newline* function_body
  672. auto start_index = m_token_index;
  673. ArmedScopeGuard reset = [&] {
  674. m_token_index = start_index;
  675. };
  676. if (peek().type != Token::Type::VariableName) {
  677. return nullptr;
  678. }
  679. auto name = consume();
  680. if (consume().type != Token::Type::OpenParen)
  681. return nullptr;
  682. if (consume().type != Token::Type::CloseParen)
  683. return nullptr;
  684. while (peek().type == Token::Type::Newline)
  685. skip();
  686. auto body = parse_function_body();
  687. if (!body)
  688. return nullptr;
  689. reset.disarm();
  690. return make_ref_counted<AST::FunctionDeclaration>(
  691. name.position.value_or(empty_position()).with_end(peek().position.value_or(empty_position())),
  692. AST::NameWithPosition { name.value, name.position.value_or(empty_position()) },
  693. Vector<AST::NameWithPosition> {},
  694. body.release_nonnull());
  695. }
  696. RefPtr<AST::Node> Parser::parse_function_body()
  697. {
  698. // compound_command redirect_list?
  699. auto node = parse_compound_command();
  700. if (!node)
  701. return nullptr;
  702. if (auto list = parse_redirect_list()) {
  703. auto position = list->position();
  704. node = make_ref_counted<AST::Join>(
  705. node->position().with_end(position),
  706. *node,
  707. list.release_nonnull());
  708. }
  709. return node;
  710. }
  711. RefPtr<AST::Node> Parser::parse_redirect_list()
  712. {
  713. // io_redirect*
  714. RefPtr<AST::Node> node;
  715. for (;;) {
  716. auto new_node = parse_io_redirect();
  717. if (!new_node)
  718. break;
  719. if (node) {
  720. node = make_ref_counted<AST::Join>(
  721. node->position().with_end(new_node->position()),
  722. *node,
  723. new_node.release_nonnull());
  724. } else {
  725. node = new_node;
  726. }
  727. }
  728. return node;
  729. }
  730. RefPtr<AST::Node> Parser::parse_compound_command()
  731. {
  732. if (auto node = parse_brace_group())
  733. return node;
  734. if (auto node = parse_subshell())
  735. return node;
  736. if (auto node = parse_if_clause())
  737. return node;
  738. if (auto node = parse_for_clause())
  739. return node;
  740. if (auto node = parse_case_clause())
  741. return node;
  742. if (auto node = parse_while_clause())
  743. return node;
  744. if (auto node = parse_until_clause())
  745. return node;
  746. return {};
  747. }
  748. RefPtr<AST::Node> Parser::parse_while_clause()
  749. {
  750. if (peek().type != Token::Type::While)
  751. return nullptr;
  752. auto start_position = consume().position.value_or(empty_position());
  753. auto condition = parse_compound_list();
  754. if (!condition)
  755. condition = make_ref_counted<AST::SyntaxError>(
  756. peek().position.value_or(empty_position()),
  757. "Expected condition after 'while'"sv);
  758. auto do_group = parse_do_group();
  759. if (!do_group)
  760. do_group = make_ref_counted<AST::SyntaxError>(
  761. peek().position.value_or(empty_position()),
  762. "Expected 'do' after 'while'"sv);
  763. // while foo; bar -> loop { if foo { bar } else { break } }
  764. return make_ref_counted<AST::ForLoop>(
  765. start_position.with_end(peek().position.value_or(empty_position())),
  766. Optional<AST::NameWithPosition> {},
  767. Optional<AST::NameWithPosition> {},
  768. nullptr,
  769. make_ref_counted<AST::IfCond>(
  770. start_position.with_end(peek().position.value_or(empty_position())),
  771. Optional<AST::Position> {},
  772. condition.release_nonnull(),
  773. do_group.release_nonnull(),
  774. make_ref_counted<AST::ContinuationControl>(
  775. start_position,
  776. AST::ContinuationControl::ContinuationKind::Break)));
  777. }
  778. RefPtr<AST::Node> Parser::parse_until_clause()
  779. {
  780. if (peek().type != Token::Type::Until)
  781. return nullptr;
  782. auto start_position = consume().position.value_or(empty_position());
  783. auto condition = parse_compound_list();
  784. if (!condition)
  785. condition = make_ref_counted<AST::SyntaxError>(
  786. peek().position.value_or(empty_position()),
  787. "Expected condition after 'until'"sv);
  788. auto do_group = parse_do_group();
  789. if (!do_group)
  790. do_group = make_ref_counted<AST::SyntaxError>(
  791. peek().position.value_or(empty_position()),
  792. "Expected 'do' after 'until'"sv);
  793. // until foo; bar -> loop { if foo { break } else { bar } }
  794. return make_ref_counted<AST::ForLoop>(
  795. start_position.with_end(peek().position.value_or(empty_position())),
  796. Optional<AST::NameWithPosition> {},
  797. Optional<AST::NameWithPosition> {},
  798. nullptr,
  799. make_ref_counted<AST::IfCond>(
  800. start_position.with_end(peek().position.value_or(empty_position())),
  801. Optional<AST::Position> {},
  802. condition.release_nonnull(),
  803. make_ref_counted<AST::ContinuationControl>(
  804. start_position,
  805. AST::ContinuationControl::ContinuationKind::Break),
  806. do_group.release_nonnull()));
  807. }
  808. RefPtr<AST::Node> Parser::parse_brace_group()
  809. {
  810. if (peek().type != Token::Type::OpenBrace)
  811. return nullptr;
  812. consume();
  813. auto list = parse_compound_list();
  814. RefPtr<AST::SyntaxError> error;
  815. if (peek().type != Token::Type::CloseBrace) {
  816. error = make_ref_counted<AST::SyntaxError>(
  817. peek().position.value_or(empty_position()),
  818. DeprecatedString::formatted("Expected '}}', not {}", peek().type_name()));
  819. } else {
  820. consume();
  821. }
  822. if (error) {
  823. if (list)
  824. list->set_is_syntax_error(*error);
  825. else
  826. list = error;
  827. }
  828. return make_ref_counted<AST::Execute>(list->position(), *list);
  829. }
  830. RefPtr<AST::Node> Parser::parse_case_clause()
  831. {
  832. auto start_position = peek().position.value_or(empty_position());
  833. if (peek().type != Token::Type::Case)
  834. return nullptr;
  835. skip();
  836. RefPtr<AST::SyntaxError> syntax_error;
  837. auto expr = parse_word();
  838. if (!expr)
  839. expr = make_ref_counted<AST::SyntaxError>(
  840. peek().position.value_or(empty_position()),
  841. DeprecatedString::formatted("Expected a word, not {}", peek().type_name()));
  842. if (peek().type != Token::Type::In) {
  843. syntax_error = make_ref_counted<AST::SyntaxError>(
  844. peek().position.value_or(empty_position()),
  845. DeprecatedString::formatted("Expected 'in', not {}", peek().type_name()));
  846. } else {
  847. skip();
  848. }
  849. while (peek().type == Token::Type::Newline)
  850. skip();
  851. Vector<AST::MatchEntry> entries;
  852. for (;;) {
  853. if (eof() || peek().type == Token::Type::Esac)
  854. break;
  855. if (peek().type == Token::Type::Newline) {
  856. skip();
  857. continue;
  858. }
  859. // Parse a pattern list
  860. auto needs_dsemi = true;
  861. if (peek().type == Token::Type::OpenParen) {
  862. skip();
  863. needs_dsemi = false;
  864. }
  865. auto result = parse_case_list();
  866. if (peek().type == Token::Type::CloseParen) {
  867. skip();
  868. } else {
  869. if (!syntax_error)
  870. syntax_error = make_ref_counted<AST::SyntaxError>(
  871. peek().position.value_or(empty_position()),
  872. DeprecatedString::formatted("Expected ')', not {}", peek().type_name()));
  873. break;
  874. }
  875. while (peek().type == Token::Type::Newline)
  876. skip();
  877. auto compound_list = parse_compound_list();
  878. if (peek().type == Token::Type::DoubleSemicolon) {
  879. skip();
  880. } else if (needs_dsemi) {
  881. if (!syntax_error)
  882. syntax_error = make_ref_counted<AST::SyntaxError>(
  883. peek().position.value_or(empty_position()),
  884. DeprecatedString::formatted("Expected ';;', not {}", peek().type_name()));
  885. }
  886. if (syntax_error) {
  887. if (compound_list)
  888. compound_list->set_is_syntax_error(*syntax_error);
  889. else
  890. compound_list = syntax_error;
  891. syntax_error = nullptr;
  892. }
  893. entries.append(AST::MatchEntry {
  894. .options = move(result.nodes),
  895. .match_names = {},
  896. .match_as_position = {},
  897. .pipe_positions = move(result.pipe_positions),
  898. .body = move(compound_list),
  899. });
  900. }
  901. if (peek().type != Token::Type::Esac) {
  902. syntax_error = make_ref_counted<AST::SyntaxError>(
  903. peek().position.value_or(empty_position()),
  904. DeprecatedString::formatted("Expected 'esac', not {}", peek().type_name()));
  905. } else {
  906. skip();
  907. }
  908. auto node = make_ref_counted<AST::MatchExpr>(
  909. start_position.with_end(peek().position.value_or(empty_position())),
  910. expr.release_nonnull(),
  911. DeprecatedString {},
  912. Optional<AST::Position> {},
  913. move(entries));
  914. if (syntax_error)
  915. node->set_is_syntax_error(*syntax_error);
  916. return node;
  917. }
  918. Parser::CaseItemsResult Parser::parse_case_list()
  919. {
  920. // Just a list of words split by '|', delimited by ')'
  921. NonnullRefPtrVector<AST::Node> nodes;
  922. Vector<AST::Position> pipes;
  923. for (;;) {
  924. if (eof() || peek().type == Token::Type::CloseParen)
  925. break;
  926. if (peek().type != Token::Type::Word)
  927. break;
  928. auto node = parse_word();
  929. if (!node)
  930. node = make_ref_counted<AST::SyntaxError>(
  931. peek().position.value_or(empty_position()),
  932. DeprecatedString::formatted("Expected a word, not {}", peek().type_name()));
  933. nodes.append(node.release_nonnull());
  934. if (peek().type == Token::Type::Pipe) {
  935. pipes.append(peek().position.value_or(empty_position()));
  936. skip();
  937. } else {
  938. break;
  939. }
  940. }
  941. if (nodes.is_empty())
  942. nodes.append(make_ref_counted<AST::SyntaxError>(
  943. peek().position.value_or(empty_position()),
  944. DeprecatedString::formatted("Expected a word, not {}", peek().type_name())));
  945. return { move(pipes), move(nodes) };
  946. }
  947. RefPtr<AST::Node> Parser::parse_if_clause()
  948. {
  949. // If compound_list Then compound_list {Elif compound_list Then compound_list (Fi|Else)?} [(?=Else) compound_list] (?!=Fi) Fi
  950. auto start_position = peek().position.value_or(empty_position());
  951. if (peek().type != Token::Type::If)
  952. return nullptr;
  953. skip();
  954. auto main_condition = parse_compound_list();
  955. if (!main_condition)
  956. main_condition = make_ref_counted<AST::SyntaxError>(empty_position(), "Expected compound list after 'if'");
  957. RefPtr<AST::SyntaxError> syntax_error;
  958. if (peek().type != Token::Type::Then) {
  959. syntax_error = make_ref_counted<AST::SyntaxError>(
  960. peek().position.value_or(empty_position()),
  961. DeprecatedString::formatted("Expected 'then', not {}", peek().type_name()));
  962. } else {
  963. skip();
  964. }
  965. auto main_consequence = parse_compound_list();
  966. if (!main_consequence)
  967. main_consequence = make_ref_counted<AST::SyntaxError>(empty_position(), "Expected compound list after 'then'");
  968. auto node = make_ref_counted<AST::IfCond>(start_position, Optional<AST::Position>(), main_condition.release_nonnull(), main_consequence.release_nonnull(), nullptr);
  969. auto active_node = node;
  970. while (peek().type == Token::Type::Elif) {
  971. skip();
  972. auto condition = parse_compound_list();
  973. if (!condition)
  974. condition = make_ref_counted<AST::SyntaxError>(empty_position(), "Expected compound list after 'elif'");
  975. if (peek().type != Token::Type::Then) {
  976. if (!syntax_error)
  977. syntax_error = make_ref_counted<AST::SyntaxError>(
  978. peek().position.value_or(empty_position()),
  979. DeprecatedString::formatted("Expected 'then', not {}", peek().type_name()));
  980. } else {
  981. skip();
  982. }
  983. auto consequence = parse_compound_list();
  984. if (!consequence)
  985. consequence = make_ref_counted<AST::SyntaxError>(empty_position(), "Expected compound list after 'then'");
  986. auto new_node = make_ref_counted<AST::IfCond>(start_position, Optional<AST::Position>(), condition.release_nonnull(), consequence.release_nonnull(), nullptr);
  987. active_node->false_branch() = new_node;
  988. active_node = move(new_node);
  989. }
  990. auto needs_fi = true;
  991. switch (peek().type) {
  992. case Token::Type::Else:
  993. skip();
  994. active_node->false_branch() = parse_compound_list();
  995. if (!active_node->false_branch())
  996. active_node->false_branch() = make_ref_counted<AST::SyntaxError>(empty_position(), "Expected compound list after 'else'");
  997. break;
  998. case Token::Type::Fi:
  999. needs_fi = false;
  1000. break;
  1001. default:
  1002. if (!syntax_error)
  1003. syntax_error = make_ref_counted<AST::SyntaxError>(
  1004. peek().position.value_or(empty_position()),
  1005. DeprecatedString::formatted("Expected 'else' or 'fi', not {}", peek().type_name()));
  1006. break;
  1007. }
  1008. if (needs_fi) {
  1009. if (peek().type != Token::Type::Fi) {
  1010. if (!syntax_error)
  1011. syntax_error = make_ref_counted<AST::SyntaxError>(
  1012. peek().position.value_or(empty_position()),
  1013. DeprecatedString::formatted("Expected 'fi', not {}", peek().type_name()));
  1014. } else {
  1015. skip();
  1016. }
  1017. }
  1018. if (syntax_error)
  1019. node->set_is_syntax_error(*syntax_error);
  1020. return node;
  1021. }
  1022. RefPtr<AST::Node> Parser::parse_subshell()
  1023. {
  1024. auto start_position = peek().position.value_or(empty_position());
  1025. if (peek().type != Token::Type::OpenParen)
  1026. return nullptr;
  1027. skip();
  1028. RefPtr<AST::SyntaxError> error;
  1029. auto list = parse_compound_list();
  1030. if (!list)
  1031. error = make_ref_counted<AST::SyntaxError>(peek().position.value_or(empty_position()), "Expected compound list after ("sv);
  1032. if (peek().type != Token::Type::CloseParen)
  1033. error = make_ref_counted<AST::SyntaxError>(peek().position.value_or(empty_position()), "Expected ) after compound list"sv);
  1034. else
  1035. skip();
  1036. if (!list)
  1037. return error;
  1038. return make_ref_counted<AST::Subshell>(
  1039. start_position.with_end(peek().position.value_or(empty_position())),
  1040. list.release_nonnull());
  1041. }
  1042. RefPtr<AST::Node> Parser::parse_compound_list()
  1043. {
  1044. while (peek().type == Token::Type::Newline)
  1045. skip();
  1046. auto term = parse_term();
  1047. if (!term)
  1048. return term;
  1049. if (is_separator(peek())) {
  1050. if (consume().type == Token::Type::And) {
  1051. term = make_ref_counted<AST::Background>(
  1052. term->position().with_end(peek().position.value_or(empty_position())),
  1053. *term);
  1054. }
  1055. }
  1056. return term;
  1057. }
  1058. RefPtr<AST::Node> Parser::parse_term()
  1059. {
  1060. NonnullRefPtrVector<AST::Node> nodes;
  1061. Vector<AST::Position> positions;
  1062. auto start_position = peek().position.value_or(empty_position());
  1063. for (;;) {
  1064. auto new_node = parse_and_or();
  1065. if (!new_node)
  1066. break;
  1067. nodes.append(new_node.release_nonnull());
  1068. if (!is_separator(peek()))
  1069. break;
  1070. auto position = consume().position;
  1071. if (position.has_value())
  1072. positions.append(position.release_value());
  1073. }
  1074. auto end_position = peek().position.value_or(empty_position());
  1075. return make_ref_counted<AST::Sequence>(
  1076. start_position.with_end(end_position),
  1077. move(nodes),
  1078. move(positions));
  1079. }
  1080. RefPtr<AST::Node> Parser::parse_for_clause()
  1081. {
  1082. // FOR NAME newline+ do_group
  1083. // FOR NAME newline+ IN separator do_group
  1084. // FOR NAME IN separator do_group
  1085. // FOR NAME IN wordlist separator do_group
  1086. if (peek().type != Token::Type::For)
  1087. return nullptr;
  1088. auto start_position = consume().position.value_or(empty_position());
  1089. DeprecatedString name;
  1090. Optional<AST::Position> name_position;
  1091. if (peek().type == Token::Type::VariableName) {
  1092. name_position = peek().position;
  1093. name = consume().value;
  1094. } else {
  1095. name = "it";
  1096. error(peek(), "Expected a variable name, not {}", peek().type_name());
  1097. }
  1098. auto saw_newline = false;
  1099. while (peek().type == Token::Type::Newline) {
  1100. saw_newline = true;
  1101. skip();
  1102. }
  1103. auto saw_in = false;
  1104. Optional<AST::Position> in_kw_position;
  1105. if (peek().type == Token::Type::In) {
  1106. saw_in = true;
  1107. in_kw_position = peek().position;
  1108. skip();
  1109. } else if (!saw_newline) {
  1110. error(peek(), "Expected 'in' or a newline, not {}", peek().type_name());
  1111. }
  1112. RefPtr<AST::Node> iterated_expression;
  1113. if (!saw_newline)
  1114. iterated_expression = parse_word_list();
  1115. if (saw_in) {
  1116. if (peek().type == Token::Type::Semicolon)
  1117. skip();
  1118. else
  1119. error(peek(), "Expected a semicolon, not {}", peek().type_name());
  1120. }
  1121. auto body = parse_do_group();
  1122. return AST::make_ref_counted<AST::ForLoop>(
  1123. start_position.with_end(peek().position.value_or(empty_position())),
  1124. AST::NameWithPosition { move(name), name_position.value_or(empty_position()) },
  1125. Optional<AST::NameWithPosition> {},
  1126. move(iterated_expression),
  1127. move(body),
  1128. move(in_kw_position),
  1129. Optional<AST::Position> {});
  1130. }
  1131. RefPtr<AST::Node> Parser::parse_word_list()
  1132. {
  1133. NonnullRefPtrVector<AST::Node> nodes;
  1134. auto start_position = peek().position.value_or(empty_position());
  1135. for (; peek().type == Token::Type::Word;) {
  1136. auto word = parse_word();
  1137. nodes.append(word.release_nonnull());
  1138. }
  1139. return make_ref_counted<AST::ListConcatenate>(
  1140. start_position.with_end(peek().position.value_or(empty_position())),
  1141. move(nodes));
  1142. }
  1143. RefPtr<AST::Node> Parser::parse_word()
  1144. {
  1145. if (peek().type != Token::Type::Word)
  1146. return nullptr;
  1147. auto token = consume();
  1148. RefPtr<AST::Node> word;
  1149. enum class Quote {
  1150. None,
  1151. Single,
  1152. Double,
  1153. } in_quote { Quote::None };
  1154. auto append_bareword = [&](StringView string) {
  1155. if (!word && string.starts_with('~')) {
  1156. GenericLexer lexer { string };
  1157. lexer.ignore();
  1158. auto user = lexer.consume_while(is_ascii_alphanumeric);
  1159. string = lexer.remaining();
  1160. word = make_ref_counted<AST::Tilde>(token.position.value_or(empty_position()), user);
  1161. }
  1162. if (string.is_empty())
  1163. return;
  1164. auto node = make_ref_counted<AST::BarewordLiteral>(token.position.value_or(empty_position()), string);
  1165. if (word) {
  1166. word = make_ref_counted<AST::Juxtaposition>(
  1167. word->position().with_end(token.position.value_or(empty_position())),
  1168. *word,
  1169. move(node),
  1170. AST::Juxtaposition::Mode::StringExpand);
  1171. } else {
  1172. word = move(node);
  1173. }
  1174. };
  1175. auto append_string_literal = [&](StringView string) {
  1176. if (string.is_empty())
  1177. return;
  1178. auto node = make_ref_counted<AST::StringLiteral>(token.position.value_or(empty_position()), string, AST::StringLiteral::EnclosureType::SingleQuotes);
  1179. if (word) {
  1180. word = make_ref_counted<AST::Juxtaposition>(
  1181. word->position().with_end(token.position.value_or(empty_position())),
  1182. *word,
  1183. move(node),
  1184. AST::Juxtaposition::Mode::StringExpand);
  1185. } else {
  1186. word = move(node);
  1187. }
  1188. };
  1189. auto append_string_part = [&](StringView string) {
  1190. if (string.is_empty())
  1191. return;
  1192. auto node = make_ref_counted<AST::StringLiteral>(token.position.value_or(empty_position()), string, AST::StringLiteral::EnclosureType::DoubleQuotes);
  1193. if (word) {
  1194. word = make_ref_counted<AST::Juxtaposition>(
  1195. word->position().with_end(token.position.value_or(empty_position())),
  1196. *word,
  1197. move(node),
  1198. AST::Juxtaposition::Mode::StringExpand);
  1199. } else {
  1200. word = move(node);
  1201. }
  1202. };
  1203. auto append_parameter_expansion = [&](ResolvedParameterExpansion const& x) {
  1204. DeprecatedString immediate_function_name;
  1205. RefPtr<AST::Node> node;
  1206. switch (x.op) {
  1207. case ResolvedParameterExpansion::Op::UseDefaultValue:
  1208. immediate_function_name = "value_or_default";
  1209. break;
  1210. case ResolvedParameterExpansion::Op::AssignDefaultValue:
  1211. immediate_function_name = "assign_default";
  1212. break;
  1213. case ResolvedParameterExpansion::Op::IndicateErrorIfEmpty:
  1214. immediate_function_name = "error_if_empty";
  1215. break;
  1216. case ResolvedParameterExpansion::Op::UseAlternativeValue:
  1217. immediate_function_name = "null_or_alternative";
  1218. break;
  1219. case ResolvedParameterExpansion::Op::UseDefaultValueIfUnset:
  1220. immediate_function_name = "defined_value_or_default";
  1221. break;
  1222. case ResolvedParameterExpansion::Op::AssignDefaultValueIfUnset:
  1223. immediate_function_name = "assign_defined_default";
  1224. break;
  1225. case ResolvedParameterExpansion::Op::IndicateErrorIfUnset:
  1226. immediate_function_name = "error_if_unset";
  1227. break;
  1228. case ResolvedParameterExpansion::Op::UseAlternativeValueIfUnset:
  1229. immediate_function_name = "null_if_unset_or_alternative";
  1230. break;
  1231. case ResolvedParameterExpansion::Op::RemoveLargestSuffixByPattern:
  1232. // FIXME: Implement this
  1233. case ResolvedParameterExpansion::Op::RemoveSmallestSuffixByPattern:
  1234. immediate_function_name = "remove_suffix";
  1235. break;
  1236. case ResolvedParameterExpansion::Op::RemoveLargestPrefixByPattern:
  1237. // FIXME: Implement this
  1238. case ResolvedParameterExpansion::Op::RemoveSmallestPrefixByPattern:
  1239. immediate_function_name = "remove_prefix";
  1240. break;
  1241. case ResolvedParameterExpansion::Op::StringLength:
  1242. immediate_function_name = "length_of_variable";
  1243. break;
  1244. case ResolvedParameterExpansion::Op::GetPositionalParameter:
  1245. case ResolvedParameterExpansion::Op::GetVariable:
  1246. node = make_ref_counted<AST::SimpleVariable>(
  1247. token.position.value_or(empty_position()),
  1248. x.parameter);
  1249. break;
  1250. case ResolvedParameterExpansion::Op::GetLastBackgroundPid:
  1251. node = make_ref_counted<AST::SyntaxError>(
  1252. token.position.value_or(empty_position()),
  1253. "$! not implemented");
  1254. break;
  1255. case ResolvedParameterExpansion::Op::GetPositionalParameterList:
  1256. node = make_ref_counted<AST::SpecialVariable>(
  1257. token.position.value_or(empty_position()),
  1258. '*');
  1259. break;
  1260. case ResolvedParameterExpansion::Op::GetCurrentOptionFlags:
  1261. node = make_ref_counted<AST::SyntaxError>(
  1262. token.position.value_or(empty_position()),
  1263. "The current option flags are not available in parameter expansions");
  1264. break;
  1265. case ResolvedParameterExpansion::Op::GetPositionalParameterCount:
  1266. node = make_ref_counted<AST::SpecialVariable>(
  1267. token.position.value_or(empty_position()),
  1268. '#');
  1269. break;
  1270. case ResolvedParameterExpansion::Op::GetLastExitStatus:
  1271. node = make_ref_counted<AST::SpecialVariable>(
  1272. token.position.value_or(empty_position()),
  1273. '?');
  1274. break;
  1275. case ResolvedParameterExpansion::Op::GetPositionalParameterListAsString:
  1276. node = make_ref_counted<AST::SyntaxError>(
  1277. token.position.value_or(empty_position()),
  1278. "$* not implemented");
  1279. break;
  1280. case ResolvedParameterExpansion::Op::GetShellProcessId:
  1281. node = make_ref_counted<AST::SpecialVariable>(
  1282. token.position.value_or(empty_position()),
  1283. '$');
  1284. break;
  1285. }
  1286. if (!node) {
  1287. NonnullRefPtrVector<AST::Node> arguments;
  1288. arguments.append(make_ref_counted<AST::BarewordLiteral>(
  1289. token.position.value_or(empty_position()),
  1290. x.parameter));
  1291. if (!x.argument.is_empty()) {
  1292. // dbgln("Will parse {}", x.argument);
  1293. arguments.append(*Parser { x.argument }.parse_word());
  1294. }
  1295. node = make_ref_counted<AST::ImmediateExpression>(
  1296. token.position.value_or(empty_position()),
  1297. AST::NameWithPosition {
  1298. immediate_function_name,
  1299. token.position.value_or(empty_position()),
  1300. },
  1301. move(arguments),
  1302. Optional<AST::Position> {});
  1303. }
  1304. if (x.expand == ResolvedParameterExpansion::Expand::Word) {
  1305. node = make_ref_counted<AST::ImmediateExpression>(
  1306. token.position.value_or(empty_position()),
  1307. AST::NameWithPosition {
  1308. "reexpand",
  1309. token.position.value_or(empty_position()),
  1310. },
  1311. Vector { node.release_nonnull() },
  1312. Optional<AST::Position> {});
  1313. }
  1314. if (word) {
  1315. word = make_ref_counted<AST::Juxtaposition>(
  1316. word->position().with_end(token.position.value_or(empty_position())),
  1317. *word,
  1318. node.release_nonnull(),
  1319. AST::Juxtaposition::Mode::StringExpand);
  1320. } else {
  1321. word = move(node);
  1322. }
  1323. };
  1324. auto append_command_expansion = [&](ResolvedCommandExpansion const& x) {
  1325. if (!x.command)
  1326. return;
  1327. RefPtr<AST::Execute> execute_node;
  1328. if (x.command->is_execute()) {
  1329. execute_node = const_cast<AST::Execute&>(static_cast<AST::Execute const&>(*x.command));
  1330. execute_node->capture_stdout();
  1331. } else {
  1332. execute_node = make_ref_counted<AST::Execute>(
  1333. word ? word->position() : empty_position(),
  1334. *x.command,
  1335. true);
  1336. }
  1337. if (word) {
  1338. word = make_ref_counted<AST::Juxtaposition>(
  1339. word->position(),
  1340. *word,
  1341. execute_node.release_nonnull(),
  1342. AST::Juxtaposition::Mode::StringExpand);
  1343. } else {
  1344. word = move(execute_node);
  1345. }
  1346. };
  1347. auto append_string = [&](StringView string) {
  1348. if (string.is_empty())
  1349. return;
  1350. Optional<size_t> run_start;
  1351. auto escape = false;
  1352. for (size_t i = 0; i < string.length(); ++i) {
  1353. auto ch = string[i];
  1354. switch (ch) {
  1355. case '\\':
  1356. if (!escape && i + 1 < string.length()) {
  1357. if (is_one_of(string[i + 1], '"', '\'', '$', '`', '\\')) {
  1358. escape = in_quote != Quote::Single;
  1359. continue;
  1360. }
  1361. }
  1362. break;
  1363. case '\'':
  1364. if (in_quote == Quote::Single) {
  1365. in_quote = Quote::None;
  1366. append_string_literal(string.substring_view(*run_start, i - *run_start));
  1367. run_start = i + 1;
  1368. continue;
  1369. }
  1370. if (in_quote == Quote::Double) {
  1371. escape = false;
  1372. continue;
  1373. }
  1374. [[fallthrough]];
  1375. case '"':
  1376. if (ch == '\'' && in_quote == Quote::Single) {
  1377. escape = false;
  1378. continue;
  1379. }
  1380. if (!escape) {
  1381. if (ch == '"' && in_quote == Quote::Double) {
  1382. in_quote = Quote::None;
  1383. if (run_start.has_value())
  1384. append_string_part(string.substring_view(*run_start, i - *run_start));
  1385. run_start = i + 1;
  1386. continue;
  1387. }
  1388. if (run_start.has_value())
  1389. append_bareword(string.substring_view(*run_start, i - *run_start));
  1390. in_quote = ch == '\'' ? Quote::Single : Quote::Double;
  1391. run_start = i + 1;
  1392. }
  1393. escape = false;
  1394. [[fallthrough]];
  1395. default:
  1396. if (!run_start.has_value())
  1397. run_start = i;
  1398. escape = false;
  1399. continue;
  1400. }
  1401. }
  1402. if (run_start.has_value())
  1403. append_bareword(string.substring_view(*run_start, string.length() - *run_start));
  1404. };
  1405. size_t current_offset = 0;
  1406. for (auto& expansion : token.resolved_expansions) {
  1407. expansion.visit(
  1408. [&](ResolvedParameterExpansion const& x) {
  1409. if (x.range.start >= token.value.length()) {
  1410. dbgln("Parameter expansion range {}-{} is out of bounds for '{}'", x.range.start, x.range.length, token.value);
  1411. return;
  1412. }
  1413. if (x.range.start != current_offset) {
  1414. append_string(token.value.substring_view(current_offset, x.range.start - current_offset));
  1415. current_offset = x.range.start;
  1416. }
  1417. current_offset += x.range.length;
  1418. append_parameter_expansion(x);
  1419. },
  1420. [&](ResolvedCommandExpansion const& x) {
  1421. if (x.range.start >= token.value.length()) {
  1422. dbgln("Parameter expansion range {}-{} is out of bounds for '{}'", x.range.start, x.range.length, token.value);
  1423. return;
  1424. }
  1425. if (x.range.start != current_offset) {
  1426. append_string(token.value.substring_view(current_offset, x.range.start - current_offset));
  1427. current_offset = x.range.start;
  1428. }
  1429. current_offset += x.range.length;
  1430. append_command_expansion(x);
  1431. });
  1432. }
  1433. if (current_offset >= token.value.length()) {
  1434. dbgln("Parameter expansion range {}- is out of bounds for '{}'", current_offset, token.value);
  1435. return word;
  1436. }
  1437. if (current_offset != token.value.length())
  1438. append_string(token.value.substring_view(current_offset));
  1439. return word;
  1440. }
  1441. RefPtr<AST::Node> Parser::parse_do_group()
  1442. {
  1443. if (peek().type != Token::Type::Do) {
  1444. return make_ref_counted<AST::SyntaxError>(
  1445. peek().position.value_or(empty_position()),
  1446. DeprecatedString::formatted("Expected 'do', not {}", peek().type_name()));
  1447. }
  1448. consume();
  1449. auto list = parse_compound_list();
  1450. RefPtr<AST::SyntaxError> error;
  1451. if (peek().type != Token::Type::Done) {
  1452. error = make_ref_counted<AST::SyntaxError>(
  1453. peek().position.value_or(empty_position()),
  1454. DeprecatedString::formatted("Expected 'done', not {}", peek().type_name()));
  1455. } else {
  1456. consume();
  1457. }
  1458. if (error) {
  1459. if (list)
  1460. list->set_is_syntax_error(*error);
  1461. else
  1462. list = error;
  1463. }
  1464. return make_ref_counted<AST::Execute>(list->position(), *list);
  1465. }
  1466. RefPtr<AST::Node> Parser::parse_simple_command()
  1467. {
  1468. auto start_position = peek().position.value_or(empty_position());
  1469. Vector<DeprecatedString> definitions;
  1470. NonnullRefPtrVector<AST::Node> nodes;
  1471. for (;;) {
  1472. if (auto io_redirect = parse_io_redirect())
  1473. nodes.append(*io_redirect);
  1474. else
  1475. break;
  1476. }
  1477. while (peek().type == Token::Type::AssignmentWord) {
  1478. definitions.append(peek().value);
  1479. if (!nodes.is_empty()) {
  1480. nodes.append(
  1481. make_ref_counted<AST::BarewordLiteral>(
  1482. peek().position.value_or(empty_position()),
  1483. consume().value));
  1484. } else {
  1485. // env (assignments) (command)
  1486. nodes.append(make_ref_counted<AST::BarewordLiteral>(
  1487. empty_position(),
  1488. "env"));
  1489. nodes.append(
  1490. make_ref_counted<AST::BarewordLiteral>(
  1491. peek().position.value_or(empty_position()),
  1492. consume().value));
  1493. }
  1494. }
  1495. // WORD or io_redirect: IO_NUMBER or io_file
  1496. if (!is_one_of(peek().type,
  1497. Token::Type::Word, Token::Type::IoNumber,
  1498. Token::Type::Less, Token::Type::LessAnd, Token::Type::Great, Token::Type::GreatAnd,
  1499. Token::Type::DoubleGreat, Token::Type::LessGreat, Token::Type::Clobber)) {
  1500. if (!nodes.is_empty()) {
  1501. Vector<AST::VariableDeclarations::Variable> variables;
  1502. for (auto& definition : definitions) {
  1503. auto parts = definition.split_limit('=', 2, SplitBehavior::KeepEmpty);
  1504. auto name = make_ref_counted<AST::BarewordLiteral>(
  1505. empty_position(),
  1506. parts[0]);
  1507. auto value = make_ref_counted<AST::BarewordLiteral>(
  1508. empty_position(),
  1509. parts.size() > 1 ? parts[1] : "");
  1510. variables.append({ move(name), move(value) });
  1511. }
  1512. return make_ref_counted<AST::VariableDeclarations>(empty_position(), move(variables));
  1513. }
  1514. return nullptr;
  1515. }
  1516. // auto first = true;
  1517. for (;;) {
  1518. if (peek().type == Token::Type::Word) {
  1519. auto new_word = parse_word();
  1520. if (!new_word)
  1521. break;
  1522. // if (first) {
  1523. // first = false;
  1524. // new_word = make_ref_counted<AST::ImmediateExpression>(
  1525. // new_word->position(),
  1526. // AST::NameWithPosition {
  1527. // "substitute_aliases"sv,
  1528. // empty_position(),
  1529. // },
  1530. // NonnullRefPtrVector<AST::Node> { *new_word },
  1531. // Optional<AST::Position> {});
  1532. // }
  1533. nodes.append(new_word.release_nonnull());
  1534. } else if (auto io_redirect = parse_io_redirect()) {
  1535. nodes.append(io_redirect.release_nonnull());
  1536. } else {
  1537. break;
  1538. }
  1539. }
  1540. auto node = make_ref_counted<AST::ListConcatenate>(
  1541. start_position.with_end(peek().position.value_or(empty_position())),
  1542. move(nodes));
  1543. return node;
  1544. }
  1545. RefPtr<AST::Node> Parser::parse_io_redirect()
  1546. {
  1547. auto start_position = peek().position.value_or(empty_position());
  1548. auto start_index = m_token_index;
  1549. // io_redirect: IO_NUMBER? io_file | IO_NUMBER? io_here
  1550. Optional<int> io_number;
  1551. if (peek().type == Token::Type::IoNumber)
  1552. io_number = consume().value.to_int(TrimWhitespace::No);
  1553. if (auto io_file = parse_io_file(start_position, io_number))
  1554. return io_file;
  1555. // if (auto io_here = parse_io_here(start_position, io_number))
  1556. // return io_here;
  1557. m_token_index = start_index;
  1558. return nullptr;
  1559. }
  1560. RefPtr<AST::Node> Parser::parse_io_file(AST::Position start_position, Optional<int> fd)
  1561. {
  1562. auto start_index = m_token_index;
  1563. // io_file = (LESS | LESSAND | GREAT | GREATAND | DGREAT | LESSGREAT | CLOBBER) WORD
  1564. auto io_operator = peek().type;
  1565. if (!is_one_of(io_operator,
  1566. Token::Type::Less, Token::Type::LessAnd, Token::Type::Great, Token::Type::GreatAnd,
  1567. Token::Type::DoubleGreat, Token::Type::LessGreat, Token::Type::Clobber))
  1568. return nullptr;
  1569. auto io_operator_token = consume();
  1570. auto word = parse_word();
  1571. if (!word) {
  1572. m_token_index = start_index;
  1573. return nullptr;
  1574. }
  1575. auto position = start_position.with_end(peek().position.value_or(empty_position()));
  1576. switch (io_operator) {
  1577. case Token::Type::Less:
  1578. return make_ref_counted<AST::ReadRedirection>(
  1579. position,
  1580. fd.value_or(0),
  1581. word.release_nonnull());
  1582. case Token::Type::Clobber:
  1583. // FIXME: Add support for clobber (and 'noclobber')
  1584. case Token::Type::Great:
  1585. return make_ref_counted<AST::WriteRedirection>(
  1586. position,
  1587. fd.value_or(1),
  1588. word.release_nonnull());
  1589. case Token::Type::DoubleGreat:
  1590. return make_ref_counted<AST::WriteAppendRedirection>(
  1591. position,
  1592. fd.value_or(1),
  1593. word.release_nonnull());
  1594. case Token::Type::LessGreat:
  1595. return make_ref_counted<AST::ReadWriteRedirection>(
  1596. position,
  1597. fd.value_or(0),
  1598. word.release_nonnull());
  1599. case Token::Type::LessAnd:
  1600. case Token::Type::GreatAnd: {
  1601. auto is_less = io_operator == Token::Type::LessAnd;
  1602. auto source_fd = fd.value_or(is_less ? 0 : 1);
  1603. if (word->is_bareword()) {
  1604. auto maybe_target_fd = static_ptr_cast<AST::BarewordLiteral>(word)->text().to_int(AK::TrimWhitespace::No);
  1605. if (maybe_target_fd.has_value()) {
  1606. auto target_fd = maybe_target_fd.release_value();
  1607. if (is_less)
  1608. swap(source_fd, target_fd);
  1609. return make_ref_counted<AST::Fd2FdRedirection>(
  1610. position,
  1611. source_fd,
  1612. target_fd);
  1613. }
  1614. }
  1615. if (is_less) {
  1616. return make_ref_counted<AST::ReadRedirection>(
  1617. position,
  1618. source_fd,
  1619. word.release_nonnull());
  1620. }
  1621. return make_ref_counted<AST::WriteRedirection>(
  1622. position,
  1623. source_fd,
  1624. word.release_nonnull());
  1625. }
  1626. default:
  1627. VERIFY_NOT_REACHED();
  1628. }
  1629. }
  1630. }