ADD: int literal.
parent
dfd65e5fc3
commit
149f866172
|
@ -0,0 +1,26 @@
|
|||
#include "Factory.hpp"
|
||||
|
||||
namespace jk
|
||||
{
|
||||
/*explicit*/ Factory::Factory(Logger& logger, std::filesystem::path path)
|
||||
: m_logger { logger }
|
||||
, m_path { path }
|
||||
{
|
||||
}
|
||||
|
||||
/*virtual*/ Factory::~Factory()
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<Lexer> Factory::make_lexer()
|
||||
{
|
||||
Loc loc {m_path, 1, 0};
|
||||
return std::make_shared<Lexer>(m_logger, loc);
|
||||
}
|
||||
|
||||
std::shared_ptr<Parser> Factory::make_parser()
|
||||
{
|
||||
auto lexer = make_lexer();
|
||||
return std::make_shared<Parser>(m_logger, lexer);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef jk_FACTORY_HPP
|
||||
#define jk_FACTORY_HPP
|
||||
|
||||
#include "Lexer.hpp"
|
||||
#include "Parser.hpp"
|
||||
#include "Logger.hpp"
|
||||
#include "commons.hpp"
|
||||
|
||||
namespace jk
|
||||
{
|
||||
class Factory
|
||||
{
|
||||
public:
|
||||
explicit Factory(Logger& logger, std::filesystem::path path);
|
||||
virtual ~Factory();
|
||||
|
||||
std::shared_ptr<Lexer> make_lexer();
|
||||
std::shared_ptr<Parser> make_parser();
|
||||
|
||||
private:
|
||||
Logger& m_logger;
|
||||
std::filesystem::path m_path;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,130 @@
|
|||
#include "Lexer.hpp"
|
||||
|
||||
namespace jk
|
||||
{
|
||||
/*explicit*/ Lexer::Lexer(Logger& logger, Loc const& loc)
|
||||
: m_logger { logger }
|
||||
, m_loc { loc }
|
||||
{
|
||||
m_scanners.push_back(std::bind(&Lexer::scan_int, this));
|
||||
}
|
||||
|
||||
/*virtual*/ Lexer::~Lexer()
|
||||
{
|
||||
}
|
||||
|
||||
void Lexer::scan(std::string const& source)
|
||||
{
|
||||
m_source = source;
|
||||
m_cursor = 0;
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> Lexer::next()
|
||||
{
|
||||
skip_spaces();
|
||||
|
||||
while (more(m_cursor)
|
||||
&& current(m_cursor) == '#')
|
||||
{
|
||||
while (more(m_cursor)
|
||||
&& current(m_cursor) != '\n')
|
||||
{
|
||||
m_cursor++;
|
||||
}
|
||||
|
||||
skip_spaces();
|
||||
}
|
||||
|
||||
std::optional<ScanInfo> info;
|
||||
|
||||
for (auto scanner: m_scanners)
|
||||
{
|
||||
auto my_info = scanner();
|
||||
|
||||
if ((!info && my_info)
|
||||
|| (info && my_info
|
||||
&& my_info->cursor > info->cursor))
|
||||
{
|
||||
info = my_info;
|
||||
}
|
||||
}
|
||||
|
||||
if (info)
|
||||
{
|
||||
m_cursor = info->cursor;
|
||||
return std::make_shared<Node>(info->type, info->repr, m_loc);
|
||||
}
|
||||
|
||||
if (more(m_cursor))
|
||||
{
|
||||
std::string text;
|
||||
|
||||
while (more(m_cursor)
|
||||
&& !std::isspace(current(m_cursor)))
|
||||
{
|
||||
text += current(m_cursor);
|
||||
m_cursor++;
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "unknown text '" << text << "'";
|
||||
m_logger.log<lexical_error>(LOG_ERROR, m_loc, ss.str());
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Lexer::more(size_t index) const
|
||||
{
|
||||
return index < m_source.size();
|
||||
}
|
||||
|
||||
char Lexer::current(size_t index) const
|
||||
{
|
||||
assert(more(index));
|
||||
|
||||
return m_source[index];
|
||||
}
|
||||
|
||||
void Lexer::skip_spaces()
|
||||
{
|
||||
while (more(m_cursor)
|
||||
&& std::isspace(current(m_cursor)))
|
||||
{
|
||||
if (current(m_cursor) == '\n')
|
||||
{
|
||||
m_loc = Loc {
|
||||
m_loc.path(),
|
||||
m_loc.line() + 1,
|
||||
m_loc.column()
|
||||
};
|
||||
}
|
||||
|
||||
m_cursor++;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<ScanInfo> Lexer::scan_int() const
|
||||
{
|
||||
size_t cursor = m_cursor;
|
||||
std::string repr;
|
||||
|
||||
while (more(cursor)
|
||||
&& std::isdigit(current(cursor)))
|
||||
{
|
||||
repr += current(cursor);
|
||||
cursor++;
|
||||
}
|
||||
|
||||
if (repr.empty() == false)
|
||||
{
|
||||
return ScanInfo {
|
||||
cursor,
|
||||
NODE_INT,
|
||||
repr
|
||||
};
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
#ifndef jk_LEXER_HPP
|
||||
#define jk_LEXER_HPP
|
||||
|
||||
#include "commons.hpp"
|
||||
#include "Logger.hpp"
|
||||
#include "Node.hpp"
|
||||
|
||||
namespace jk
|
||||
{
|
||||
JK_ERROR(lexical_error);
|
||||
|
||||
struct ScanInfo {
|
||||
size_t cursor;
|
||||
NodeType type;
|
||||
std::string repr;
|
||||
};
|
||||
|
||||
using scanner_t = std::function<std::optional<ScanInfo>()>;
|
||||
|
||||
class Lexer
|
||||
{
|
||||
public:
|
||||
explicit Lexer(Logger& logger, Loc const& loc);
|
||||
virtual ~Lexer();
|
||||
|
||||
void scan(std::string const& source);
|
||||
std::shared_ptr<Node> next();
|
||||
|
||||
private:
|
||||
Logger& m_logger;
|
||||
Loc m_loc;
|
||||
size_t m_cursor;
|
||||
std::string m_source;
|
||||
std::vector<scanner_t> m_scanners;
|
||||
|
||||
bool more(size_t index) const;
|
||||
char current(size_t index) const;
|
||||
|
||||
void skip_spaces();
|
||||
|
||||
std::optional<ScanInfo> scan_int() const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,15 @@
|
|||
#include "Loc.hpp"
|
||||
|
||||
namespace jk
|
||||
{
|
||||
/*explicit*/ Loc::Loc(std::filesystem::path path, int line, int column)
|
||||
: m_path { path }
|
||||
, m_line { line }
|
||||
, m_column { column }
|
||||
{
|
||||
}
|
||||
|
||||
/*virtual*/ Loc::~Loc()
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef jk_LOC_HPP
|
||||
#define jk_LOC_HPP
|
||||
|
||||
#include "commons.hpp"
|
||||
|
||||
namespace jk
|
||||
{
|
||||
class Loc
|
||||
{
|
||||
public:
|
||||
explicit Loc(std::filesystem::path path, int line, int column);
|
||||
virtual ~Loc();
|
||||
|
||||
std::filesystem::path path() const { return m_path; }
|
||||
int line() const { return m_line; }
|
||||
int column() const { return m_column; }
|
||||
|
||||
private:
|
||||
std::filesystem::path m_path;
|
||||
int m_line;
|
||||
int m_column;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,12 @@
|
|||
#include "Logger.hpp"
|
||||
|
||||
namespace jk
|
||||
{
|
||||
/*explicit*/ Logger::Logger()
|
||||
{
|
||||
}
|
||||
|
||||
/*virtual*/ Logger::~Logger()
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef jk_LOGGER_HPP
|
||||
#define jk_LOGGER_HPP
|
||||
|
||||
#include "commons.hpp"
|
||||
#include "Loc.hpp"
|
||||
|
||||
#define LOG_TYPE(G) \
|
||||
G(LOG_ERROR)
|
||||
|
||||
namespace jk
|
||||
{
|
||||
JK_ENUM(Log, LOG_TYPE);
|
||||
|
||||
class Logger
|
||||
{
|
||||
public:
|
||||
explicit Logger();
|
||||
virtual ~Logger();
|
||||
|
||||
template<typename T>
|
||||
void log(LogType type, Loc const& loc, std::string const& what);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void Logger::log(LogType type, Loc const& loc, std::string const& what)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << loc.path().string() << ":" << loc.line();
|
||||
ss << " " << (std::string(LogTypeStr[type])
|
||||
.substr(std::string("LOG_").size()));
|
||||
ss << " " << what;
|
||||
|
||||
throw T { ss.str() };
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,57 @@
|
|||
#include "Node.hpp"
|
||||
|
||||
namespace jk
|
||||
{
|
||||
/*explicit*/ Node::Node(NodeType type,
|
||||
std::string const& repr,
|
||||
Loc const& loc)
|
||||
: m_type { type }
|
||||
, m_repr { repr }
|
||||
, m_loc { loc }
|
||||
{
|
||||
}
|
||||
|
||||
/*virtual*/ Node::~Node()
|
||||
{
|
||||
}
|
||||
|
||||
void Node::add_child(std::shared_ptr<Node> child)
|
||||
{
|
||||
m_children.push_back(child);
|
||||
}
|
||||
|
||||
std::weak_ptr<Node> Node::child(size_t index) const
|
||||
{
|
||||
assert(index < size());
|
||||
return m_children[index];
|
||||
}
|
||||
|
||||
std::string Node::string() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::string(NodeTypeStr[m_type])
|
||||
.substr(std::string("NODE_").size());
|
||||
|
||||
if (m_repr.empty() == false)
|
||||
{
|
||||
ss << "[" << m_repr << "]";
|
||||
}
|
||||
|
||||
if (size() > 0)
|
||||
{
|
||||
ss << "(";
|
||||
|
||||
std::string sep;
|
||||
|
||||
for (auto child: m_children)
|
||||
{
|
||||
ss << sep << child->string();
|
||||
sep = ",";
|
||||
}
|
||||
|
||||
ss << ")";
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef jk_NODE_HPP
|
||||
#define jk_NODE_HPP
|
||||
|
||||
#include "commons.hpp"
|
||||
#include "Loc.hpp"
|
||||
|
||||
#define NODE_TYPE(G) \
|
||||
G(NODE_PROG), \
|
||||
G(NODE_INT)
|
||||
|
||||
namespace jk
|
||||
{
|
||||
JK_ENUM(Node, NODE_TYPE);
|
||||
|
||||
class Node
|
||||
{
|
||||
public:
|
||||
explicit Node(NodeType type, std::string const& repr, Loc const& loc);
|
||||
virtual ~Node();
|
||||
|
||||
NodeType type() const { return m_type; }
|
||||
std::string repr() const { return m_repr; }
|
||||
Loc const& loc() const { return m_loc; }
|
||||
size_t size() const { return m_children.size(); }
|
||||
|
||||
void add_child(std::shared_ptr<Node> child);
|
||||
std::weak_ptr<Node> child(size_t index) const;
|
||||
|
||||
std::string string() const;
|
||||
|
||||
private:
|
||||
NodeType m_type;
|
||||
std::string m_repr;
|
||||
Loc m_loc;
|
||||
std::vector<std::shared_ptr<Node>> m_children;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,19 @@
|
|||
#include "Parser.hpp"
|
||||
|
||||
namespace jk
|
||||
{
|
||||
/*explicit*/ Parser::Parser(Logger& logger, std::shared_ptr<Lexer> lexer)
|
||||
: m_logger { logger }
|
||||
, m_lexer { lexer }
|
||||
{
|
||||
}
|
||||
|
||||
/*virtual*/ Parser::~Parser()
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> Parser::parse(std::string const&)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef jk_PARSER_HPP
|
||||
#define jk_PARSER_HPP
|
||||
|
||||
#include "commons.hpp"
|
||||
#include "Logger.hpp"
|
||||
#include "Lexer.hpp"
|
||||
|
||||
namespace jk
|
||||
{
|
||||
class Parser
|
||||
{
|
||||
public:
|
||||
explicit Parser(Logger& logger, std::shared_ptr<Lexer> lexer);
|
||||
virtual ~Parser();
|
||||
|
||||
std::shared_ptr<Node> parse(std::string const& source);
|
||||
|
||||
private:
|
||||
Logger& m_logger;
|
||||
std::shared_ptr<Lexer> m_lexer;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,13 @@
|
|||
#include "Type.hpp"
|
||||
|
||||
namespace jk
|
||||
{
|
||||
/*explicit*/ Type::Type(TypeType type)
|
||||
: m_type { type }
|
||||
{
|
||||
}
|
||||
|
||||
/*virtual*/ Type::~Type()
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef jk_TYPE_HPP
|
||||
#define jk_TYPE_HPP
|
||||
|
||||
#include "commons.hpp"
|
||||
|
||||
#define TYPE_TYPE(G) \
|
||||
G(TYPE_NIL), \
|
||||
G(TYPE_INT)
|
||||
|
||||
namespace jk
|
||||
{
|
||||
JK_ENUM(Type, TYPE_TYPE);
|
||||
|
||||
class Type
|
||||
{
|
||||
public:
|
||||
explicit Type(TypeType type);
|
||||
virtual ~Type();
|
||||
|
||||
TypeType type() const { return m_type; }
|
||||
private:
|
||||
TypeType m_type;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,25 @@
|
|||
#include "Value.hpp"
|
||||
#include "Type.hpp"
|
||||
|
||||
namespace jk
|
||||
{
|
||||
/*static*/ std::shared_ptr<Value> Value::make_nil()
|
||||
{
|
||||
auto value = std::make_shared<Value>();
|
||||
value->m_type = std::make_shared<Type>(TYPE_NIL);
|
||||
return value;
|
||||
}
|
||||
|
||||
/*static*/ std::shared_ptr<Value> Value::make_int(int val)
|
||||
{
|
||||
auto value = std::make_shared<Value>();
|
||||
value->m_type = std::make_shared<Type>(TYPE_INT);
|
||||
value->m_int_val = val;
|
||||
return value;
|
||||
}
|
||||
|
||||
std::weak_ptr<Type> Value::type() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef jk_VALUE_HPP
|
||||
#define jk_VALUE_HPP
|
||||
|
||||
#include "commons.hpp"
|
||||
|
||||
namespace jk
|
||||
{
|
||||
class Type;
|
||||
|
||||
class Value
|
||||
{
|
||||
public:
|
||||
static std::shared_ptr<Value> make_nil();
|
||||
static std::shared_ptr<Value> make_int(int val);
|
||||
|
||||
explicit Value() = default;
|
||||
virtual ~Value() = default;
|
||||
|
||||
int as_int() const { return *m_int_val; }
|
||||
|
||||
std::weak_ptr<Type> type() const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<Type> m_type;
|
||||
std::optional<int> m_int_val;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,6 +1,18 @@
|
|||
#ifndef jk_COMMONS_HPP
|
||||
#define jk_COMMONS_HPP
|
||||
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
|
||||
#include "mutils.hpp"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,18 @@
|
|||
#ifndef jk_MUTILS_HPP
|
||||
#define jk_MUTILS_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#define ENUM_ENUM(X) X
|
||||
#define ENUM_STRING(X) #X
|
||||
|
||||
#define JK_ENUM(PREFIX, DECL) \
|
||||
enum PREFIX ## Type { DECL(ENUM_ENUM) }; \
|
||||
constexpr char const* PREFIX ## TypeStr [] { DECL(ENUM_STRING) }
|
||||
|
||||
#define JK_ERROR(NAME) \
|
||||
struct NAME : public std::runtime_error { \
|
||||
NAME (std::string const& what): std::runtime_error {what} {} \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
16
meson.build
16
meson.build
|
@ -21,6 +21,18 @@ configure_file(
|
|||
joko_lib = static_library(
|
||||
'joko',
|
||||
sources: [
|
||||
'lib/Node.cpp',
|
||||
'lib/Loc.cpp',
|
||||
|
||||
'lib/Factory.cpp',
|
||||
|
||||
'lib/Logger.cpp',
|
||||
'lib/Lexer.cpp',
|
||||
'lib/Parser.cpp',
|
||||
|
||||
'lib/Type.cpp',
|
||||
'lib/Value.cpp',
|
||||
|
||||
],
|
||||
dependencies: [
|
||||
])
|
||||
|
@ -38,7 +50,9 @@ executable('joko',
|
|||
|
||||
executable('joko-tests',
|
||||
sources: [
|
||||
'tests/main.cpp'
|
||||
'tests/main.cpp',
|
||||
'tests/Lexer.cpp',
|
||||
'tests/Parser.cpp',
|
||||
],
|
||||
dependencies: [
|
||||
joko_dep,
|
||||
|
|
53
src/main.cpp
53
src/main.cpp
|
@ -1,21 +1,26 @@
|
|||
#include <iostream>
|
||||
#include <getopt.h>
|
||||
#include "config.hpp"
|
||||
#include "../lib/Lexer.hpp"
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int index;
|
||||
bool debug_mode = false;
|
||||
|
||||
struct option options[] = {
|
||||
{"debug", no_argument, 0, 'd'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"version", no_argument, 0, 'v'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
int c = getopt_long(argc, argv, "hv", options, &index);
|
||||
int c = getopt_long(argc, argv, "dhv", options, &index);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 'd': debug_mode = true; break;
|
||||
|
||||
case 'h': {
|
||||
std::cout << "Usage: joko [OPTIONS] source_file" << std::endl;
|
||||
std::cout << "OPTIONS" << std::endl;
|
||||
|
@ -37,5 +42,51 @@ int main(int argc, char** argv)
|
|||
|
||||
}
|
||||
|
||||
if (optind < argc)
|
||||
{
|
||||
jk::Logger logger;
|
||||
jk::Loc loc {argv[optind], 1, 1};
|
||||
|
||||
std::ifstream file { argv[optind] };
|
||||
|
||||
if (!file)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "cannot find file '" << argv[optind] << "'";
|
||||
logger.log<std::runtime_error>(jk::LOG_ERROR, loc, ss.str());
|
||||
}
|
||||
|
||||
std::string source;
|
||||
std::string line;
|
||||
|
||||
while (std::getline(file, line))
|
||||
{
|
||||
source += line + (file.eof() ? "" : "\n");
|
||||
}
|
||||
|
||||
jk::Lexer lexer {logger, loc};
|
||||
lexer.scan(source);
|
||||
|
||||
if (debug_mode)
|
||||
{
|
||||
std::cout << "--- tokens ---" << std::endl;
|
||||
std::shared_ptr<jk::Node> tok;
|
||||
|
||||
std::string sep;
|
||||
while ( (tok = lexer.next()) )
|
||||
{
|
||||
std::cout << sep << tok->string();
|
||||
sep = " ";
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
#include <catch2/catch.hpp>
|
||||
#include "../lib/Lexer.hpp"
|
||||
#include "../lib/Factory.hpp"
|
||||
|
||||
class LexerTest
|
||||
{
|
||||
public:
|
||||
explicit LexerTest() {}
|
||||
virtual ~LexerTest() {}
|
||||
|
||||
void test_next(jk::Lexer& lexer, std::string const& oracle)
|
||||
{
|
||||
auto token = lexer.next();
|
||||
REQUIRE(token);
|
||||
REQUIRE(oracle == token->string());
|
||||
}
|
||||
|
||||
void test_end(jk::Lexer& lexer)
|
||||
{
|
||||
auto token = lexer.next();
|
||||
REQUIRE(!token);
|
||||
}
|
||||
|
||||
protected:
|
||||
jk::Logger m_logger;
|
||||
};
|
||||
|
||||
TEST_CASE_METHOD(LexerTest, "Lexer_int")
|
||||
{
|
||||
auto lexer = jk::Factory(m_logger, "tests/lexer").make_lexer();
|
||||
lexer->scan("4 128 333");
|
||||
test_next(*lexer, "INT[4]");
|
||||
test_next(*lexer, "INT[128]");
|
||||
test_next(*lexer, "INT[333]");
|
||||
test_end(*lexer);
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(LexerTest, "Lexer_comments")
|
||||
{
|
||||
auto lexer = jk::Factory(m_logger, "tests/lexer").make_lexer();
|
||||
lexer->scan("4 # 128 \n 333");
|
||||
test_next(*lexer, "INT[4]");
|
||||
test_next(*lexer, "INT[333]");
|
||||
test_end(*lexer);
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(LexerTest, "Lexer_error")
|
||||
{
|
||||
auto lexer = jk::Factory(m_logger, "tests/lexer").make_lexer();
|
||||
lexer->scan(" § ");
|
||||
REQUIRE_THROWS_AS(lexer->next(), jk::lexical_error);
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
#include <catch2/catch.hpp>
|
||||
#include "../lib/Parser.hpp"
|
||||
#include "../lib/Factory.hpp"
|
||||
|
||||
class ParserTest
|
||||
{
|
||||
public:
|
||||
explicit ParserTest() {}
|
||||
virtual ~ParserTest() {}
|
||||
|
||||
protected:
|
||||
jk::Logger m_logger;
|
||||
};
|
||||
|
||||
TEST_CASE_METHOD(ParserTest, "Parser_")
|
||||
{
|
||||
}
|
Reference in New Issue