buffalo
Loading...
Searching...
No Matches
buffalo.test.cpp
Go to the documentation of this file.
1#include <gtest/gtest.h>
2#include <buffalo/buffalo.h>
3#include <cmath>
4
5/*
6 * Grammar Definition
7 */
9
10/*
11 * Terminals
12 */
13bf::DefineTerminal<G, R"(\d+(\.\d+)?)", double> NUMBER([](auto const &tok) {
14 return std::stod(std::string(tok.raw));
15});
16
18
23
24bf::DefineTerminal<G, R"(\‍()"> PAR_OPEN;
26
27/*
28 * Non-Terminals
29 */
31 = bf::PR<G>(NUMBER)<=>[](auto &$) { return $[0]; }
32 | (PAR_OPEN + expression + PAR_CLOSE)<=>[](auto &$) { return $[1]; }
33 | (expression + OP_EXP + expression)<=>[](auto &$) { return std::pow($[0], $[2]); }
34 | (expression + OP_MUL + expression)<=>[](auto &$) { return $[0] * $[2]; }
35 | (expression + OP_DIV + expression)<=>[](auto &$) { return $[0] / $[2]; }
36 | (expression + OP_ADD + expression)<=>[](auto &$) { return $[0] + $[2]; }
37 | (expression + OP_SUB + expression)<=>[](auto &$) { return $[0] - $[2]; }
38 ;
39
41 = bf::PR<G>(expression)<=>[](auto &$)
42 {
43 return $[0];
44 }
45 ;
46
47TEST(Parser, Construction)
48{
50 ASSERT_TRUE(parser.has_value());
51}
52
53TEST(Parser, Evaluation)
54{
55 auto parser = *bf::SLRParser<G>::Build(statement);
56
57 auto res = parser.Parse("3 * 3 + 4^2 - (9 / 3)");
58 ASSERT_TRUE(res.has_value());
59
60 ASSERT_EQ(*res, 22.0);
61}
62
63TEST(Tokenization, Strict)
64{
65 auto parser = *bf::SLRParser<G>::Build(statement);
66
67 std::vector<bf::Token<G>> tokens;
68 auto result = parser.Parse("3 + 5 - 2", &tokens);
69
70 ASSERT_TRUE(result.has_value());
71
72 ASSERT_EQ(tokens.size(), 5);
73
74 ASSERT_EQ(tokens[0].terminal, &NUMBER);
75 ASSERT_EQ(tokens[0].location.begin, 0);
76
77 ASSERT_EQ(tokens[1].terminal, &OP_ADD);
78 ASSERT_EQ(tokens[1].location.begin, 2);
79
80 ASSERT_EQ(tokens[2].terminal, &NUMBER);
81 ASSERT_EQ(tokens[2].location.begin, 4);
82
83 ASSERT_EQ(tokens[3].terminal, &OP_SUB);
84 ASSERT_EQ(tokens[3].location.begin, 6);
85
86 ASSERT_EQ(tokens[4].terminal, &NUMBER);
87 ASSERT_EQ(tokens[4].location.begin, 8);
88}
89
90TEST(Tokenization, Permissive)
91{
92 auto parser = *bf::SLRParser<G>::Build(statement);
93
94 std::vector<bf::Token<G>> tokens;
95 auto result = parser.Parse("3[[[+]]]&0", &tokens);
96
97 ASSERT_FALSE(result.has_value());
98
99 ASSERT_EQ(tokens.size(), 3);
100
101 ASSERT_EQ(tokens[0].terminal, &NUMBER);
102 ASSERT_EQ(tokens[0].location.begin, 0);
103
104 ASSERT_EQ(tokens[1].terminal, &OP_ADD);
105 ASSERT_EQ(tokens[1].location.begin, 4);
106
107 ASSERT_EQ(tokens[2].terminal, &NUMBER);
108 ASSERT_EQ(tokens[2].location.begin, 9);
109}
bf::GrammarDefinition< double > G
bf::DefineNonTerminal< G > expression
bf::DefineTerminal< G, R"(\*)"> OP_MUL(bf::Left)
bf::DefineTerminal< G, R"(\‍()"> PAR_OPEN;bf::DefineTerminal< G, R"(\‍))"> PAR_CLOSE
bf::DefineTerminal< G, R"(\+)"> OP_ADD(bf::Left)
bf::DefineNonTerminal< G > statement
bf::DefineTerminal< G, R"(\^)"> OP_EXP(bf::Right)
bf::DefineTerminal< G, R"(\d+(\.\d+)?)", double > NUMBER([](auto const &tok) { return std::stod(std::string(tok.raw));})
bf::DefineTerminal< G, R"(\/)"> OP_DIV(bf::Left)
bf::DefineTerminal< G, R"(\-)"> OP_SUB(bf::Left)
TEST(Parser, Construction)
static std::expected< SLRParser, Error > Build(NonTerminal< G > &start)
Definition buffalo.h:1147
@ Left
Definition buffalo.h:196
@ Right
Definition buffalo.h:197
ProductionRule< G > PR
Definition buffalo.h:438