summaryrefslogtreecommitdiff
path: root/src/sexpr
diff options
context:
space:
mode:
Diffstat (limited to 'src/sexpr')
-rw-r--r--src/sexpr/bind.cpp29
-rw-r--r--src/sexpr/fwd.hpp4
-rw-r--r--src/sexpr/lexer.hpp10
-rw-r--r--src/sexpr/lexer_test.cpp32
-rw-r--r--src/sexpr/parser.hpp2
-rw-r--r--src/sexpr/parser_test.cpp25
-rw-r--r--src/sexpr/union_test.cpp (renamed from src/sexpr/union.cpp)2
-rw-r--r--src/sexpr/variant.cpp40
-rw-r--r--src/sexpr/variant.hpp49
-rw-r--r--src/sexpr/variant.tcc3
-rw-r--r--src/sexpr/variant_test.cpp32
-rw-r--r--src/sexpr/void.cpp29
12 files changed, 82 insertions, 175 deletions
diff --git a/src/sexpr/bind.cpp b/src/sexpr/bind.cpp
deleted file mode 100644
index d8d0caa..0000000
--- a/src/sexpr/bind.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-#include "bind.hpp"
-// bind.cpp - Just include the header file.
-//
-// Copyright © 2012 Ben Longbons <b.r.longbons@gmail.com>
-//
-// This file is part of The Mana World (Athena server)
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-#include "../poison.hpp"
-
-
-namespace tmwa
-{
-namespace sexpr
-{
-} // namespace sexpr
-} // namespace tmwa
diff --git a/src/sexpr/fwd.hpp b/src/sexpr/fwd.hpp
index 580b322..b86d9fb 100644
--- a/src/sexpr/fwd.hpp
+++ b/src/sexpr/fwd.hpp
@@ -20,6 +20,10 @@
#include "../sanity.hpp"
+#include "../strings/fwd.hpp" // rank 1
+#include "../io/fwd.hpp" // rank 4
+// sexpr/fwd.hpp is rank 5
+
namespace tmwa
{
diff --git a/src/sexpr/lexer.hpp b/src/sexpr/lexer.hpp
index 63be72d..9b198a0 100644
--- a/src/sexpr/lexer.hpp
+++ b/src/sexpr/lexer.hpp
@@ -22,7 +22,6 @@
#include <vector>
-#include "../strings/fwd.hpp"
#include "../strings/astring.hpp"
#include "../strings/zstring.hpp"
@@ -59,10 +58,13 @@ namespace sexpr
Lexer(ZString filename)
: _in(filename), _current(TOK_EOF), _span(), _depth()
{ adv(); }
- // for unit tests
- Lexer(ZString fake, io::FD fd)
- : _in(fake, fd), _current(TOK_EOF), _span(), _depth()
+ Lexer(io::read_file_from_string, ZString name, XString str)
+ : _in(io::from_string, name, str), _current(TOK_EOF), _span(), _depth()
{ adv(); }
+ Lexer(io::read_file_from_string, ZString name, LString str)
+ : _in(io::from_string, name, str), _current(TOK_EOF), _span(), _depth()
+ { adv(); }
+
Lexeme peek() { return _current; }
void adv() { _current = _adv(); }
ZString val_string() { return _string; }
diff --git a/src/sexpr/lexer_test.cpp b/src/sexpr/lexer_test.cpp
index fdb47f2..d84312e 100644
--- a/src/sexpr/lexer_test.cpp
+++ b/src/sexpr/lexer_test.cpp
@@ -29,22 +29,6 @@
namespace tmwa
{
-static
-io::FD string_pipe(ZString sz)
-{
- io::FD rfd, wfd;
- if (-1 == io::FD::pipe(rfd, wfd))
- return io::FD();
- if (sz.size() != wfd.write(sz.c_str(), sz.size()))
- {
- rfd.close();
- wfd.close();
- return io::FD();
- }
- wfd.close();
- return rfd;
-}
-
TEST(sexpr, escape)
{
EXPECT_EQ(sexpr::escape('\0'), "\\x00"_s);
@@ -73,24 +57,24 @@ TEST(sexpr, escape)
TEST(sexpr, lexer)
{
io::LineSpan span;
- sexpr::Lexer lexer("<lexer-test1>"_s, string_pipe(" foo( ) 123\"\" \n"_s));
+ sexpr::Lexer lexer(io::from_string, "<lexer-test1>"_s, " foo( ) 123\"\" \n"_s);
EXPECT_EQ(lexer.peek(), sexpr::TOK_TOKEN);
EXPECT_EQ(lexer.val_string(), "foo"_s);
- EXPECT_EQ(lexer.span().message_str("error"_s, "test"_s),
+ EXPECT_EQ(lexer.span().error_str("test"_s),
"<lexer-test1>:1:2: error: test\n"
" foo( ) 123\"\" \n"
" ^~~\n"_s
);
lexer.adv();
EXPECT_EQ(lexer.peek(), sexpr::TOK_OPEN);
- EXPECT_EQ(lexer.span().message_str("error"_s, "test"_s),
+ EXPECT_EQ(lexer.span().error_str("test"_s),
"<lexer-test1>:1:5: error: test\n"
" foo( ) 123\"\" \n"
" ^\n"_s
);
lexer.adv();
EXPECT_EQ(lexer.peek(), sexpr::TOK_CLOSE);
- EXPECT_EQ(lexer.span().message_str("error"_s, "test"_s),
+ EXPECT_EQ(lexer.span().error_str("test"_s),
"<lexer-test1>:1:7: error: test\n"
" foo( ) 123\"\" \n"
" ^\n"_s
@@ -98,7 +82,7 @@ TEST(sexpr, lexer)
lexer.adv();
EXPECT_EQ(lexer.peek(), sexpr::TOK_TOKEN);
EXPECT_EQ(lexer.val_string(), "123"_s);
- EXPECT_EQ(lexer.span().message_str("error"_s, "test"_s),
+ EXPECT_EQ(lexer.span().error_str("test"_s),
"<lexer-test1>:1:9: error: test\n"
" foo( ) 123\"\" \n"
" ^~~\n"_s
@@ -106,7 +90,7 @@ TEST(sexpr, lexer)
lexer.adv();
EXPECT_EQ(lexer.peek(), sexpr::TOK_STRING);
EXPECT_EQ(lexer.val_string(), ""_s);
- EXPECT_EQ(lexer.span().message_str("error"_s, "test"_s),
+ EXPECT_EQ(lexer.span().error_str("test"_s),
"<lexer-test1>:1:12: error: test\n"
" foo( ) 123\"\" \n"
" ^~\n"_s
@@ -120,7 +104,7 @@ TEST(sexpr, lexbad)
QuietFd q;
{
io::LineSpan span;
- sexpr::Lexer lexer("<lexer-bad>"_s, string_pipe("(\n"_s));
+ sexpr::Lexer lexer(io::from_string, "<lexer-bad>"_s, "(\n"_s);
EXPECT_EQ(lexer.peek(), sexpr::TOK_OPEN);
lexer.adv();
EXPECT_EQ(lexer.peek(), sexpr::TOK_ERROR);
@@ -135,7 +119,7 @@ TEST(sexpr, lexbad)
})
{
io::LineSpan span;
- sexpr::Lexer lexer("<lexer-bad>"_s, string_pipe(bad));
+ sexpr::Lexer lexer(io::from_string, "<lexer-bad>"_s, bad);
EXPECT_EQ(lexer.peek(), sexpr::TOK_ERROR);
}
}
diff --git a/src/sexpr/parser.hpp b/src/sexpr/parser.hpp
index feed636..cfe8212 100644
--- a/src/sexpr/parser.hpp
+++ b/src/sexpr/parser.hpp
@@ -22,8 +22,6 @@
#include <cstdlib>
-#include "../strings/fwd.hpp"
-
#include "../io/line.hpp"
#include "lexer.hpp"
diff --git a/src/sexpr/parser_test.cpp b/src/sexpr/parser_test.cpp
index 846d425..bbaf5eb 100644
--- a/src/sexpr/parser_test.cpp
+++ b/src/sexpr/parser_test.cpp
@@ -20,32 +20,18 @@
#include <gtest/gtest.h>
+#include "../tests/fdhack.hpp"
+
#include "../poison.hpp"
namespace tmwa
{
-static
-io::FD string_pipe(ZString sz)
-{
- io::FD rfd, wfd;
- if (-1 == io::FD::pipe(rfd, wfd))
- return io::FD();
- if (sz.size() != wfd.write(sz.c_str(), sz.size()))
- {
- rfd.close();
- wfd.close();
- return io::FD();
- }
- wfd.close();
- return rfd;
-}
-
TEST(sexpr, parser)
{
sexpr::SExpr s;
io::LineSpan span;
- sexpr::Lexer lexer("<parser-test1>"_s, string_pipe(" foo( ) 123\"\" \n"_s));
+ sexpr::Lexer lexer(io::from_string, "<parser-test1>"_s, " foo( ) 123\"\" \n"_s);
EXPECT_TRUE(sexpr::parse(lexer, s));
EXPECT_EQ(s._type, sexpr::TOKEN);
@@ -70,7 +56,7 @@ TEST(sexpr, parser)
TEST(sexpr, parselist)
{
sexpr::SExpr s;
- sexpr::Lexer lexer("<parser-test1>"_s, string_pipe("(foo)(bar)\n"_s));
+ sexpr::Lexer lexer(io::from_string, "<parser-test1>"_s, "(foo)(bar)\n"_s);
EXPECT_TRUE(sexpr::parse(lexer, s));
EXPECT_EQ(s._type, sexpr::LIST);
@@ -90,6 +76,7 @@ TEST(sexpr, parselist)
TEST(sexpr, parsebad)
{
+ QuietFd q;
for (LString bad : {
"(\n"_s,
")\n"_s,
@@ -105,7 +92,7 @@ TEST(sexpr, parsebad)
{
sexpr::SExpr s;
io::LineSpan span;
- sexpr::Lexer lexer("<parse-bad>"_s, string_pipe(bad));
+ sexpr::Lexer lexer(io::from_string, "<parse-bad>"_s, bad);
EXPECT_FALSE(sexpr::parse(lexer, s));
EXPECT_EQ(lexer.peek(), sexpr::TOK_ERROR);
}
diff --git a/src/sexpr/union.cpp b/src/sexpr/union_test.cpp
index 6f65012..ca60b49 100644
--- a/src/sexpr/union.cpp
+++ b/src/sexpr/union_test.cpp
@@ -1,5 +1,5 @@
#include "union.hpp"
-// union.cpp - Just include the header file and try to instantiate.
+// union_test.cpp - Just include the header file and try to instantiate.
//
// Copyright © 2012 Ben Longbons <b.r.longbons@gmail.com>
//
diff --git a/src/sexpr/variant.cpp b/src/sexpr/variant.cpp
deleted file mode 100644
index b1f500a..0000000
--- a/src/sexpr/variant.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "variant.hpp"
-// variant.cpp - Just include the header file.
-//
-// Copyright © 2012 Ben Longbons <b.r.longbons@gmail.com>
-//
-// This file is part of The Mana World (Athena server)
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-#include "../poison.hpp"
-
-
-namespace tmwa
-{
-namespace sexpr
-{
-namespace
-{
- struct Foo
- {
- Foo() {}
- ~Foo() {}
- Foo(Foo&&) {}
- Foo& operator = (Foo&&) { return *this; }
- };
-} // anonymous namespace
- static Variant<int, Foo> v;
-} // namespace sexpr
-} // namespace tmwa
diff --git a/src/sexpr/variant.hpp b/src/sexpr/variant.hpp
index fbf9345..0eccc5a 100644
--- a/src/sexpr/variant.hpp
+++ b/src/sexpr/variant.hpp
@@ -33,19 +33,42 @@ namespace tmwa
{
namespace sexpr
{
-#define JOIN(a, b) a##b
-
-#define WITH_VAR(ty, var, expr) \
- for (bool JOIN(var, _guard) = true; JOIN(var, _guard); ) \
- for (ty var = expr; JOIN(var, _guard); JOIN(var, _guard) = false)
-#define MATCH(expr) \
- WITH_VAR(auto&&, _match_var, expr) \
- switch (tmwa::sexpr::VariantFriend::get_state(_match_var))
-#define TYPED_CASE(ty, var, look) \
- break; \
- case tmwa::sexpr::VariantFriend::get_state_for<look, decltype(_match_var)>(): \
- WITH_VAR(ty, var, tmwa::sexpr::VariantFriend::unchecked_get<look>(_match_var))
-#define CASE(ty, var) TYPED_CASE(ty, var, std::remove_const<std::remove_reference<ty>::type>::type)
+#define MATCH_BEGIN(expr) \
+ { \
+ auto&& _match_var = (expr); \
+ switch (tmwa::sexpr::VariantFriend::get_state(_match_var)) \
+ { \
+ { \
+ { \
+ /* }}}} */
+#define MATCH_END() \
+ /* {{{{ */ \
+ } \
+ } \
+ } \
+ (void) _match_var; \
+ }
+
+#define MATCH_CASE(ty, v) \
+ /* {{{{ */ \
+ } \
+ break; \
+ } \
+ { \
+ using _match_case_type = std::remove_const<std::remove_reference<ty>::type>::type; \
+ case tmwa::sexpr::VariantFriend::get_state_for<_match_case_type, decltype(_match_var)>(): \
+ { \
+ ty v = tmwa::sexpr::VariantFriend::unchecked_get<_match_case_type>(_match_var);
+ /* }}}} */
+#define MATCH_DEFAULT() \
+ /* {{{{ */ \
+ } \
+ break; \
+ } \
+ { \
+ default: \
+ { \
+ /* }}}} */
template<class... T>
class Variant
diff --git a/src/sexpr/variant.tcc b/src/sexpr/variant.tcc
index 1f7df03..c370fa4 100644
--- a/src/sexpr/variant.tcc
+++ b/src/sexpr/variant.tcc
@@ -120,6 +120,9 @@ namespace sexpr
}
catch (...)
{
+ // TODO switch from requiring nothrow default construct, to
+ // instead require nothrow moves, and offer the strong exception
+ // guarantee (which is actually easier that the basic one)
#if GCC != 407 // apparent compiler bug, not reduced
// 4.7.2 from wheezy is bad
// 4.7.3 from jessie is good
diff --git a/src/sexpr/variant_test.cpp b/src/sexpr/variant_test.cpp
index bc378aa..c671264 100644
--- a/src/sexpr/variant_test.cpp
+++ b/src/sexpr/variant_test.cpp
@@ -77,42 +77,46 @@ TEST(variant, match)
: sexpr::Variant<Foo, Bar>(Foo(1))
{}
};
+
Sub v1;
- MATCH (v1)
+ MATCH_BEGIN (v1)
{
- // This is not a public API, it's just for testing.
- default:
- FAIL();
-
- CASE(Foo, f)
+ MATCH_DEFAULT ()
+ {
+ FAIL();
+ }
+ MATCH_CASE (Foo, f)
{
(void)f;
SUCCEED();
}
- CASE(Bar, b)
+ MATCH_CASE (Bar, b)
{
(void)b;
FAIL();
}
}
+ MATCH_END ();
+
v1.emplace<Bar>(2);
- MATCH (v1)
+ MATCH_BEGIN (v1)
{
- // This is not a public API, it's just for testing.
- default:
- FAIL();
-
- CASE(Foo, f)
+ MATCH_DEFAULT ()
+ {
+ FAIL();
+ }
+ MATCH_CASE (Foo, f)
{
(void)f;
FAIL();
}
- CASE(Bar, b)
+ MATCH_CASE (Bar, b)
{
(void)b;
SUCCEED();
}
}
+ MATCH_END ();
}
TEST(variant, copymove1)
diff --git a/src/sexpr/void.cpp b/src/sexpr/void.cpp
deleted file mode 100644
index 9f0eeb5..0000000
--- a/src/sexpr/void.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-#include "void.hpp"
-// void.cpp - Just include the header file.
-//
-// Copyright © 2012 Ben Longbons <b.r.longbons@gmail.com>
-//
-// This file is part of The Mana World (Athena server)
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-#include "../poison.hpp"
-
-
-namespace tmwa
-{
-namespace sexpr
-{
-} // namespace sexpr
-} // namespace tmwa