expr.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  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(1);
  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 { return integer() != 0; }
  333. virtual int integer() const override
  334. {
  335. if (m_op == StringOperation::Substring || m_op == StringOperation::Match) {
  336. auto substr = string();
  337. if (auto integer = substr.to_int(); integer.has_value())
  338. return integer.value();
  339. else
  340. fail("Not an integer: '{}'", substr);
  341. }
  342. if (m_op == StringOperation::Index) {
  343. if (auto idx = m_str->string().index_of(m_pos_or_chars->string()); idx.has_value())
  344. return idx.value() + 1;
  345. return 0;
  346. }
  347. if (m_op == StringOperation::Length)
  348. return m_str->string().length();
  349. VERIFY_NOT_REACHED();
  350. }
  351. static auto safe_substring(const String& str, int start, int length)
  352. {
  353. if (start < 1 || (size_t)start > str.length())
  354. fail("Index out of range");
  355. --start;
  356. if (str.length() - start < (size_t)length)
  357. fail("Index out of range");
  358. return str.substring(start, length);
  359. }
  360. virtual String string() const override
  361. {
  362. if (m_op == StringOperation::Substring)
  363. return safe_substring(m_str->string(), m_pos_or_chars->integer(), m_length->integer());
  364. if (m_op == StringOperation::Match) {
  365. auto match = m_compiled_regex->match(m_str->string(), PosixFlags::Global);
  366. if (m_compiled_regex->parser_result.capture_groups_count == 0) {
  367. if (!match.success)
  368. return "0";
  369. size_t count = 0;
  370. for (auto& m : match.matches)
  371. count += m.view.length();
  372. return String::number(count);
  373. } else {
  374. if (!match.success)
  375. return "";
  376. StringBuilder result;
  377. for (auto& m : match.capture_group_matches) {
  378. for (auto& e : m)
  379. result.append(e.view.to_string());
  380. }
  381. return result.build();
  382. }
  383. }
  384. return String::number(integer());
  385. }
  386. virtual Type type() const override
  387. {
  388. if (m_op == StringOperation::Substring)
  389. return Type::String;
  390. if (m_op == StringOperation::Match) {
  391. if (!m_pos_or_chars)
  392. fail("'match' expects a string pattern");
  393. ensure_regex();
  394. if (m_compiled_regex->parser_result.capture_groups_count == 0)
  395. return Type::Integer;
  396. return Type::String;
  397. }
  398. return Type::Integer;
  399. }
  400. void ensure_regex() const
  401. {
  402. if (!m_compiled_regex)
  403. m_compiled_regex = make<regex::Regex<PosixExtended>>(m_pos_or_chars->string());
  404. }
  405. StringOperation m_op { StringOperation::Substring };
  406. NonnullOwnPtr<Expression> m_str;
  407. OwnPtr<Expression> m_pos_or_chars, m_length;
  408. mutable OwnPtr<regex::Regex<PosixExtended>> m_compiled_regex;
  409. };
  410. NonnullOwnPtr<Expression> Expression::parse(Queue<StringView>& args, Precedence prec)
  411. {
  412. switch (prec) {
  413. case Or: {
  414. auto left = parse(args, And);
  415. while (!args.is_empty() && args.head() == "|") {
  416. args.dequeue();
  417. auto right = parse(args, And);
  418. left = make<BooleanExpression>(BooleanExpression::BooleanOperator::Or, move(left), move(right));
  419. }
  420. return left;
  421. }
  422. case And: {
  423. auto left = parse(args, Comp);
  424. while (!args.is_empty() && args.head() == "&") {
  425. args.dequeue();
  426. auto right = parse(args, Comp);
  427. left = make<BooleanExpression>(BooleanExpression::BooleanOperator::And, move(left), move(right));
  428. }
  429. return left;
  430. }
  431. case Comp: {
  432. auto left = parse(args, ArithS);
  433. while (!args.is_empty() && args.head().is_one_of("<", "<=", "=", "!=", "=>", ">")) {
  434. auto op = args.dequeue();
  435. auto right = parse(args, ArithM);
  436. left = make<ComparisonExpression>(ComparisonExpression::op_from(op), move(left), move(right));
  437. }
  438. return left;
  439. }
  440. case ArithS: {
  441. auto left = parse(args, ArithM);
  442. while (!args.is_empty() && args.head().is_one_of("+", "-")) {
  443. auto op = args.dequeue();
  444. auto right = parse(args, ArithM);
  445. left = make<ArithmeticExpression>(ArithmeticExpression::op_from(op), move(left), move(right));
  446. }
  447. return left;
  448. }
  449. case ArithM: {
  450. auto left = parse(args, StringO);
  451. while (!args.is_empty() && args.head().is_one_of("*", "/", "%")) {
  452. auto op = args.dequeue();
  453. auto right = parse(args, StringO);
  454. left = make<ArithmeticExpression>(ArithmeticExpression::op_from(op), move(left), move(right));
  455. }
  456. return left;
  457. }
  458. case StringO: {
  459. if (args.is_empty())
  460. fail("Expected a term");
  461. OwnPtr<Expression> left;
  462. while (!args.is_empty()) {
  463. auto& op = args.head();
  464. if (op == "+") {
  465. args.dequeue();
  466. left = make<ValueExpression>(args.dequeue());
  467. } else if (op == "substr") {
  468. args.dequeue();
  469. auto str = parse(args, Paren);
  470. auto pos = parse(args, Paren);
  471. auto len = parse(args, Paren);
  472. left = make<StringExpression>(StringExpression::StringOperation::Substring, move(str), move(pos), move(len));
  473. } else if (op == "index") {
  474. args.dequeue();
  475. auto str = parse(args, Paren);
  476. auto chars = parse(args, Paren);
  477. left = make<StringExpression>(StringExpression::StringOperation::Index, move(str), move(chars));
  478. } else if (op == "match") {
  479. args.dequeue();
  480. auto str = parse(args, Paren);
  481. auto pattern = parse(args, Paren);
  482. left = make<StringExpression>(StringExpression::StringOperation::Match, move(str), move(pattern));
  483. } else if (op == "length") {
  484. args.dequeue();
  485. auto str = parse(args, Paren);
  486. left = make<StringExpression>(StringExpression::StringOperation::Length, move(str));
  487. } else if (!left) {
  488. left = parse(args, Paren);
  489. }
  490. if (!args.is_empty() && args.head() == ":") {
  491. args.dequeue();
  492. auto right = parse(args, Paren);
  493. left = make<StringExpression>(StringExpression::StringOperation::Match, left.release_nonnull(), move(right));
  494. } else {
  495. return left.release_nonnull();
  496. }
  497. }
  498. return left.release_nonnull();
  499. }
  500. case Paren: {
  501. if (args.is_empty())
  502. fail("Expected a term");
  503. if (args.head() == "(") {
  504. args.dequeue();
  505. auto expr = parse(args);
  506. if (args.head() != ")")
  507. fail("Expected a close paren");
  508. args.dequeue();
  509. return expr;
  510. }
  511. return make<ValueExpression>(args.dequeue());
  512. }
  513. }
  514. fail("Invalid expression");
  515. }
  516. int main(int argc, char** argv)
  517. {
  518. if (pledge("stdio", nullptr) < 0) {
  519. perror("pledge");
  520. return 1;
  521. }
  522. if (unveil(nullptr, nullptr) < 0) {
  523. perror("unveil");
  524. return 1;
  525. }
  526. if ((argc == 2 && StringView { "--help" } == argv[1]) || argc == 1)
  527. print_help_and_exit();
  528. Queue<StringView> args;
  529. for (int i = 1; i < argc; ++i)
  530. args.enqueue(argv[i]);
  531. auto expression = Expression::parse(args);
  532. if (!args.is_empty())
  533. fail("Extra tokens at the end of the expression");
  534. switch (expression->type()) {
  535. case Expression::Type::Integer:
  536. outln("{}", expression->integer());
  537. break;
  538. case Expression::Type::String:
  539. outln("{}", expression->string());
  540. break;
  541. }
  542. return 0;
  543. }