Line data Source code
1 : // Copyright 2018 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/torque/earley-parser.h"
6 : #include "test/unittests/test-utils.h"
7 :
8 : namespace v8 {
9 : namespace internal {
10 : namespace torque {
11 :
12 : namespace {
13 :
14 : template <int op(int, int)>
15 11 : base::Optional<ParseResult> MakeBinop(ParseResultIterator* child_results) {
16 : // Ideally, we would want to use int as a result type here instead of
17 : // std::string. This is possible, but requires adding int to the list of
18 : // supported ParseResult types in torque-parser.cc. To avoid changing that
19 : // code, we use std::string here, which is already used in the Torque parser.
20 11 : auto a = child_results->NextAs<std::string>();
21 11 : auto b = child_results->NextAs<std::string>();
22 44 : return ParseResult{std::to_string(op(std::stoi(a), std::stoi(b)))};
23 : }
24 :
25 5 : int plus(int a, int b) { return a + b; }
26 2 : int minus(int a, int b) { return a - b; }
27 4 : int mul(int a, int b) { return a * b; }
28 :
29 : } // namespace
30 :
31 2 : struct SimpleArithmeticGrammar : Grammar {
32 34 : static bool MatchWhitespace(InputPosition* pos) {
33 56 : while (MatchChar(std::isspace, pos)) {
34 : }
35 34 : return true;
36 : }
37 :
38 32 : static bool MatchInteger(InputPosition* pos) {
39 32 : InputPosition current = *pos;
40 32 : MatchString("-", ¤t);
41 32 : if (MatchChar(std::isdigit, ¤t)) {
42 13 : while (MatchChar(std::isdigit, ¤t)) {
43 : }
44 13 : *pos = current;
45 13 : return true;
46 : }
47 : return false;
48 : }
49 :
50 36 : SimpleArithmeticGrammar() : Grammar(&sum_expression) {
51 : SetWhitespace(MatchWhitespace);
52 1 : }
53 :
54 : Symbol integer = {Rule({Pattern(MatchInteger)}, YieldMatchedInput)};
55 :
56 : Symbol atomic_expression = {Rule({&integer}),
57 4 : Rule({Token("("), &sum_expression, Token(")")})};
58 :
59 : Symbol mul_expression = {
60 : Rule({&atomic_expression}),
61 2 : Rule({&mul_expression, Token("*"), &atomic_expression}, MakeBinop<mul>)};
62 :
63 : Symbol sum_expression = {
64 : Rule({&mul_expression}),
65 2 : Rule({&sum_expression, Token("+"), &mul_expression}, MakeBinop<plus>),
66 2 : Rule({&sum_expression, Token("-"), &mul_expression}, MakeBinop<minus>)};
67 : };
68 :
69 15443 : TEST(EarleyParser, SimpleArithmetic) {
70 2 : SimpleArithmeticGrammar grammar;
71 1 : SourceFileMap::Scope source_file_map;
72 : CurrentSourceFile::Scope current_source_file{
73 2 : SourceFileMap::AddSource("dummy_filename")};
74 : std::string result1 =
75 3 : grammar.Parse("-5 - 5 + (3 + 5) * 2")->Cast<std::string>();
76 1 : ASSERT_EQ("6", result1);
77 3 : std::string result2 = grammar.Parse("((-1 + (1) * 2 + 3 - 4 * 5 + -6 * 7))")
78 : ->Cast<std::string>();
79 1 : ASSERT_EQ("-58", result2);
80 : }
81 :
82 : } // namespace torque
83 : } // namespace internal
84 9264 : } // namespace v8
|