expr.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. /*
  2. * Copyright (c) 2020, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Assertions.h>
  7. #include <AK/GenericLexer.h>
  8. #include <AK/NonnullOwnPtr.h>
  9. #include <AK/OwnPtr.h>
  10. #include <AK/Queue.h>
  11. #include <AK/String.h>
  12. #include <AK/StringView.h>
  13. #include <LibCore/System.h>
  14. #include <LibMain/Main.h>
  15. #include <LibRegex/Regex.h>
  16. #include <stdio.h>
  17. #include <unistd.h>
  18. static void print_help_and_exit()
  19. {
  20. outln(R"(
  21. Usage: expr EXPRESSION
  22. expr [--help]
  23. Print the value of EXPRESSION to standard output.)");
  24. exit(0);
  25. }
  26. template<typename Fmt, typename... Args>
  27. [[noreturn]] void fail(Fmt&& fmt, Args&&... args)
  28. {
  29. warn("ERROR: \e[31m");
  30. warnln(StringView { fmt }, args...);
  31. warn("\e[0m");
  32. exit(2);
  33. }
  34. class Expression {
  35. public:
  36. enum Precedence {
  37. Or,
  38. And,
  39. Comp,
  40. ArithS,
  41. ArithM,
  42. StringO,
  43. Paren,
  44. };
  45. static NonnullOwnPtr<Expression> parse(Queue<StringView>& args, Precedence prec = Or);
  46. enum class Type {
  47. Integer,
  48. String,
  49. };
  50. virtual bool truth() const = 0;
  51. virtual int integer() const = 0;
  52. virtual String string() const = 0;
  53. virtual Type type() const = 0;
  54. virtual ~Expression() { }
  55. };
  56. class ValueExpression : public Expression {
  57. public:
  58. ValueExpression(int v)
  59. : as_integer(v)
  60. , m_type(Type::Integer)
  61. {
  62. }
  63. ValueExpression(String&& v)
  64. : as_string(move(v))
  65. , m_type(Type::String)
  66. {
  67. }
  68. virtual ~ValueExpression() { }
  69. private:
  70. virtual bool truth() const override
  71. {
  72. if (m_type == Type::String)
  73. return !as_string.is_empty();
  74. return integer() != 0;
  75. }
  76. virtual int integer() const override
  77. {
  78. switch (m_type) {
  79. case Type::Integer:
  80. return as_integer;
  81. case Type::String:
  82. if (auto converted = as_string.to_int(); converted.has_value())
  83. return converted.value();
  84. fail("Not an integer: '{}'", as_string);
  85. }
  86. VERIFY_NOT_REACHED();
  87. }
  88. virtual String string() const override
  89. {
  90. switch (m_type) {
  91. case Type::Integer:
  92. return String::formatted("{}", as_integer);
  93. case Type::String:
  94. return as_string;
  95. }
  96. VERIFY_NOT_REACHED();
  97. }
  98. virtual Type type() const override { return m_type; }
  99. union {
  100. int as_integer;
  101. String as_string;
  102. };
  103. Type m_type { Type::String };
  104. };
  105. class BooleanExpression : public Expression {
  106. public:
  107. enum class BooleanOperator {
  108. And,
  109. Or,
  110. };
  111. static BooleanOperator op_from(StringView sv)
  112. {
  113. if (sv == "&")
  114. return BooleanOperator::And;
  115. return BooleanOperator::Or;
  116. }
  117. BooleanExpression(BooleanOperator op, NonnullOwnPtr<Expression>&& left, NonnullOwnPtr<Expression>&& right)
  118. : m_op(op)
  119. , m_left(move(left))
  120. , m_right(move(right))
  121. {
  122. if (m_op == BooleanOperator::Or)
  123. m_left_truth = m_left->truth();
  124. else
  125. m_right_truth = m_right->truth();
  126. }
  127. private:
  128. virtual bool truth() const override
  129. {
  130. if (m_op == BooleanOperator::Or)
  131. return m_left_truth ? true : m_right->truth();
  132. return m_right_truth ? m_left->truth() : false;
  133. }
  134. virtual int integer() const override
  135. {
  136. switch (m_op) {
  137. case BooleanOperator::And:
  138. if (m_right_truth)
  139. return m_left->integer();
  140. return 0;
  141. case BooleanOperator::Or:
  142. if (m_left_truth)
  143. return m_left->integer();
  144. return m_right->integer();
  145. }
  146. VERIFY_NOT_REACHED();
  147. }
  148. virtual String string() const override
  149. {
  150. switch (m_op) {
  151. case BooleanOperator::And:
  152. if (m_right_truth)
  153. return m_left->string();
  154. return "0";
  155. case BooleanOperator::Or:
  156. if (m_left_truth)
  157. return m_left->string();
  158. return m_right->string();
  159. }
  160. VERIFY_NOT_REACHED();
  161. }
  162. virtual Type type() const override
  163. {
  164. switch (m_op) {
  165. case BooleanOperator::And:
  166. if (m_right_truth)
  167. return m_left->type();
  168. return m_right->type();
  169. case BooleanOperator::Or:
  170. if (m_left_truth)
  171. return m_left->type();
  172. return m_right->type();
  173. }
  174. VERIFY_NOT_REACHED();
  175. }
  176. BooleanOperator m_op { BooleanOperator::And };
  177. NonnullOwnPtr<Expression> m_left, m_right;
  178. bool m_left_truth { false }, m_right_truth { false };
  179. };
  180. class ComparisonExpression : public Expression {
  181. public:
  182. enum class ComparisonOperation {
  183. Less,
  184. LessEq,
  185. Eq,
  186. Neq,
  187. GreaterEq,
  188. Greater,
  189. };
  190. static ComparisonOperation op_from(StringView sv)
  191. {
  192. if (sv == "<")
  193. return ComparisonOperation::Less;
  194. if (sv == "<=")
  195. return ComparisonOperation::LessEq;
  196. if (sv == "=")
  197. return ComparisonOperation::Eq;
  198. if (sv == "!=")
  199. return ComparisonOperation::Neq;
  200. if (sv == ">=")
  201. return ComparisonOperation::GreaterEq;
  202. return ComparisonOperation::Greater;
  203. }
  204. ComparisonExpression(ComparisonOperation op, NonnullOwnPtr<Expression>&& left, NonnullOwnPtr<Expression>&& right)
  205. : m_op(op)
  206. , m_left(move(left))
  207. , m_right(move(right))
  208. {
  209. }
  210. private:
  211. template<typename T>
  212. bool compare(const T& left, const T& right) const
  213. {
  214. switch (m_op) {
  215. case ComparisonOperation::Less:
  216. return left < right;
  217. case ComparisonOperation::LessEq:
  218. return left == right || left < right;
  219. case ComparisonOperation::Eq:
  220. return left == right;
  221. case ComparisonOperation::Neq:
  222. return left != right;
  223. case ComparisonOperation::GreaterEq:
  224. return !(left < right);
  225. case ComparisonOperation::Greater:
  226. return left != right && !(left < right);
  227. }
  228. VERIFY_NOT_REACHED();
  229. }
  230. virtual bool truth() const override
  231. {
  232. switch (m_left->type()) {
  233. case Type::Integer:
  234. return compare(m_left->integer(), m_right->integer());
  235. case Type::String:
  236. return compare(m_left->string(), m_right->string());
  237. }
  238. VERIFY_NOT_REACHED();
  239. }
  240. virtual int integer() const override { return truth(); }
  241. virtual String string() const override { return truth() ? "1" : "0"; }
  242. virtual Type type() const override { return Type::Integer; }
  243. ComparisonOperation m_op { ComparisonOperation::Less };
  244. NonnullOwnPtr<Expression> m_left, m_right;
  245. };
  246. class ArithmeticExpression : public Expression {
  247. public:
  248. enum class ArithmeticOperation {
  249. Sum,
  250. Difference,
  251. Product,
  252. Quotient,
  253. Remainder,
  254. };
  255. static ArithmeticOperation op_from(StringView sv)
  256. {
  257. if (sv == "+")
  258. return ArithmeticOperation::Sum;
  259. if (sv == "-")
  260. return ArithmeticOperation::Difference;
  261. if (sv == "*")
  262. return ArithmeticOperation::Product;
  263. if (sv == "/")
  264. return ArithmeticOperation::Quotient;
  265. return ArithmeticOperation::Remainder;
  266. }
  267. ArithmeticExpression(ArithmeticOperation op, NonnullOwnPtr<Expression>&& left, NonnullOwnPtr<Expression>&& right)
  268. : m_op(op)
  269. , m_left(move(left))
  270. , m_right(move(right))
  271. {
  272. }
  273. private:
  274. virtual bool truth() const override
  275. {
  276. switch (m_op) {
  277. case ArithmeticOperation::Sum:
  278. return m_left->truth() || m_right->truth();
  279. default:
  280. return integer() != 0;
  281. }
  282. }
  283. virtual int integer() const override
  284. {
  285. auto right = m_right->integer();
  286. if (right == 0) {
  287. if (m_op == ArithmeticOperation::Product)
  288. return 0;
  289. if (m_op == ArithmeticOperation::Quotient || m_op == ArithmeticOperation::Remainder)
  290. fail("Division by zero");
  291. }
  292. auto left = m_left->integer();
  293. switch (m_op) {
  294. case ArithmeticOperation::Product:
  295. return right * left;
  296. case ArithmeticOperation::Sum:
  297. return right + left;
  298. case ArithmeticOperation::Difference:
  299. return left - right;
  300. case ArithmeticOperation::Quotient:
  301. return left / right;
  302. case ArithmeticOperation::Remainder:
  303. return left % right;
  304. }
  305. VERIFY_NOT_REACHED();
  306. }
  307. virtual String string() const override
  308. {
  309. return String::formatted("{}", integer());
  310. }
  311. virtual Type type() const override
  312. {
  313. return Type::Integer;
  314. }
  315. ArithmeticOperation m_op { ArithmeticOperation::Sum };
  316. NonnullOwnPtr<Expression> m_left, m_right;
  317. };
  318. class StringExpression : public Expression {
  319. public:
  320. enum class StringOperation {
  321. Substring,
  322. Index,
  323. Length,
  324. Match,
  325. };
  326. StringExpression(StringOperation op, NonnullOwnPtr<Expression> string, OwnPtr<Expression> pos_or_chars = {}, OwnPtr<Expression> length = {})
  327. : m_op(op)
  328. , m_str(move(string))
  329. , m_pos_or_chars(move(pos_or_chars))
  330. , m_length(move(length))
  331. {
  332. }
  333. private:
  334. virtual bool truth() const override
  335. {
  336. if (type() == Expression::Type::String)
  337. return !string().is_empty();
  338. return integer() != 0;
  339. }
  340. virtual int integer() const override
  341. {
  342. if (m_op == StringOperation::Substring || m_op == StringOperation::Match) {
  343. auto substr = string();
  344. if (auto integer = substr.to_int(); integer.has_value())
  345. return integer.value();
  346. else
  347. fail("Not an integer: '{}'", substr);
  348. }
  349. if (m_op == StringOperation::Index) {
  350. if (auto idx = m_str->string().find(m_pos_or_chars->string()); idx.has_value())
  351. return idx.value() + 1;
  352. return 0;
  353. }
  354. if (m_op == StringOperation::Length)
  355. return m_str->string().length();
  356. VERIFY_NOT_REACHED();
  357. }
  358. static auto safe_substring(const String& str, int start, int length)
  359. {
  360. if (start < 1 || (size_t)start > str.length())
  361. fail("Index out of range");
  362. --start;
  363. if (str.length() - start < (size_t)length)
  364. fail("Index out of range");
  365. return str.substring(start, length);
  366. }
  367. virtual String string() const override
  368. {
  369. if (m_op == StringOperation::Substring)
  370. return safe_substring(m_str->string(), m_pos_or_chars->integer(), m_length->integer());
  371. if (m_op == StringOperation::Match) {
  372. auto match = m_compiled_regex->match(m_str->string(), PosixFlags::Global);
  373. if (m_compiled_regex->parser_result.capture_groups_count == 0) {
  374. if (!match.success)
  375. return "0";
  376. size_t count = 0;
  377. for (auto& m : match.matches)
  378. count += m.view.length();
  379. return String::number(count);
  380. } else {
  381. if (!match.success)
  382. return "";
  383. StringBuilder result;
  384. for (auto& e : match.capture_group_matches[0])
  385. result.append(e.view.string_view());
  386. return result.build();
  387. }
  388. }
  389. return String::number(integer());
  390. }
  391. virtual Type type() const override
  392. {
  393. if (m_op == StringOperation::Substring)
  394. return Type::String;
  395. if (m_op == StringOperation::Match) {
  396. if (!m_pos_or_chars)
  397. fail("'match' expects a string pattern");
  398. ensure_regex();
  399. if (m_compiled_regex->parser_result.capture_groups_count == 0)
  400. return Type::Integer;
  401. return Type::String;
  402. }
  403. return Type::Integer;
  404. }
  405. void ensure_regex() const
  406. {
  407. if (!m_compiled_regex) {
  408. m_compiled_regex = make<regex::Regex<PosixBasic>>(m_pos_or_chars->string());
  409. if (m_compiled_regex->parser_result.error != regex::Error::NoError)
  410. fail("Regex error: {}", regex::get_error_string(m_compiled_regex->parser_result.error));
  411. }
  412. }
  413. StringOperation m_op { StringOperation::Substring };
  414. NonnullOwnPtr<Expression> m_str;
  415. OwnPtr<Expression> m_pos_or_chars, m_length;
  416. mutable OwnPtr<regex::Regex<PosixBasic>> m_compiled_regex;
  417. };
  418. NonnullOwnPtr<Expression> Expression::parse(Queue<StringView>& args, Precedence prec)
  419. {
  420. switch (prec) {
  421. case Or: {
  422. auto left = parse(args, And);
  423. while (!args.is_empty() && args.head() == "|") {
  424. args.dequeue();
  425. auto right = parse(args, And);
  426. left = make<BooleanExpression>(BooleanExpression::BooleanOperator::Or, move(left), move(right));
  427. }
  428. return left;
  429. }
  430. case And: {
  431. auto left = parse(args, Comp);
  432. while (!args.is_empty() && args.head() == "&") {
  433. args.dequeue();
  434. auto right = parse(args, Comp);
  435. left = make<BooleanExpression>(BooleanExpression::BooleanOperator::And, move(left), move(right));
  436. }
  437. return left;
  438. }
  439. case Comp: {
  440. auto left = parse(args, ArithS);
  441. while (!args.is_empty() && args.head().is_one_of("<", "<=", "=", "!=", "=>", ">")) {
  442. auto op = args.dequeue();
  443. auto right = parse(args, ArithM);
  444. left = make<ComparisonExpression>(ComparisonExpression::op_from(op), move(left), move(right));
  445. }
  446. return left;
  447. }
  448. case ArithS: {
  449. auto left = parse(args, ArithM);
  450. while (!args.is_empty() && args.head().is_one_of("+", "-")) {
  451. auto op = args.dequeue();
  452. auto right = parse(args, ArithM);
  453. left = make<ArithmeticExpression>(ArithmeticExpression::op_from(op), move(left), move(right));
  454. }
  455. return left;
  456. }
  457. case ArithM: {
  458. auto left = parse(args, StringO);
  459. while (!args.is_empty() && args.head().is_one_of("*", "/", "%")) {
  460. auto op = args.dequeue();
  461. auto right = parse(args, StringO);
  462. left = make<ArithmeticExpression>(ArithmeticExpression::op_from(op), move(left), move(right));
  463. }
  464. return left;
  465. }
  466. case StringO: {
  467. if (args.is_empty())
  468. fail("Expected a term");
  469. OwnPtr<Expression> left;
  470. while (!args.is_empty()) {
  471. auto& op = args.head();
  472. if (op == "+") {
  473. args.dequeue();
  474. left = make<ValueExpression>(args.dequeue());
  475. } else if (op == "substr") {
  476. args.dequeue();
  477. auto str = parse(args, Paren);
  478. auto pos = parse(args, Paren);
  479. auto len = parse(args, Paren);
  480. left = make<StringExpression>(StringExpression::StringOperation::Substring, move(str), move(pos), move(len));
  481. } else if (op == "index") {
  482. args.dequeue();
  483. auto str = parse(args, Paren);
  484. auto chars = parse(args, Paren);
  485. left = make<StringExpression>(StringExpression::StringOperation::Index, move(str), move(chars));
  486. } else if (op == "match") {
  487. args.dequeue();
  488. auto str = parse(args, Paren);
  489. auto pattern = parse(args, Paren);
  490. left = make<StringExpression>(StringExpression::StringOperation::Match, move(str), move(pattern));
  491. } else if (op == "length") {
  492. args.dequeue();
  493. auto str = parse(args, Paren);
  494. left = make<StringExpression>(StringExpression::StringOperation::Length, move(str));
  495. } else if (!left) {
  496. left = parse(args, Paren);
  497. }
  498. if (!args.is_empty() && args.head() == ":") {
  499. args.dequeue();
  500. auto right = parse(args, Paren);
  501. left = make<StringExpression>(StringExpression::StringOperation::Match, left.release_nonnull(), move(right));
  502. } else {
  503. return left.release_nonnull();
  504. }
  505. }
  506. return left.release_nonnull();
  507. }
  508. case Paren: {
  509. if (args.is_empty())
  510. fail("Expected a term");
  511. if (args.head() == "(") {
  512. args.dequeue();
  513. auto expr = parse(args);
  514. if (args.head() != ")")
  515. fail("Expected a close paren");
  516. args.dequeue();
  517. return expr;
  518. }
  519. return make<ValueExpression>(args.dequeue());
  520. }
  521. }
  522. fail("Invalid expression");
  523. }
  524. ErrorOr<int> serenity_main(Main::Arguments arguments)
  525. {
  526. TRY(Core::System::pledge("stdio"sv));
  527. TRY(Core::System::unveil(nullptr, nullptr));
  528. if ((arguments.strings.size() == 2 && "--help"sv == arguments.strings[1]) || arguments.strings.size() == 1)
  529. print_help_and_exit();
  530. Queue<StringView> args;
  531. for (size_t i = 1; i < arguments.strings.size(); ++i)
  532. args.enqueue(arguments.strings[i]);
  533. auto expression = Expression::parse(args);
  534. if (!args.is_empty())
  535. fail("Extra tokens at the end of the expression");
  536. switch (expression->type()) {
  537. case Expression::Type::Integer:
  538. outln("{}", expression->integer());
  539. break;
  540. case Expression::Type::String:
  541. outln("{}", expression->string());
  542. break;
  543. }
  544. return expression->truth() ? 0 : 1;
  545. }