expr.cpp 17 KB

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