Skip to content

Commit aa552e6

Browse files
committed
feat: switch to nlohmann::json
1 parent 6cca0a3 commit aa552e6

File tree

6 files changed

+80
-91
lines changed

6 files changed

+80
-91
lines changed

CMakeLists.txt

+3-10
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ include(GNUInstallDirs)
1414
if(MSVC)
1515
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:__cplusplus /utf-8 /D_CRT_SECURE_NO_DEPRECATE /W4 /WX")
1616
else()
17-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -Werror")
17+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic")
1818
endif()
1919

2020
include(cmake/CPM.cmake)
@@ -58,14 +58,7 @@ include_directories(${PYTHON_INCLUDE_DIRS})
5858

5959
# CPM Packages
6060

61-
CPMAddPackage(
62-
NAME simdjson
63-
VERSION 3.11.3
64-
GITHUB_REPOSITORY simdjson/simdjson
65-
OPTIONS
66-
# "SIMDJSON_BUILD_STATIC_LIB ON"
67-
# "BUILD_SHARED_LIBS ON"
68-
)
61+
CPMAddPackage("gh:nlohmann/[email protected]")
6962

7063
CPMAddPackage(
7164
NAME cxxopts
@@ -89,4 +82,4 @@ target_include_directories(
8982

9083
target_include_directories(${PROJECT_NAME} PUBLIC ${PYTHON_INCLUDE_DIRS})
9184

92-
target_link_libraries(${PROJECT_NAME} PUBLIC simdjson::simdjson Python3::Python cxxopts::cxxopts)
85+
target_link_libraries(${PROJECT_NAME} PUBLIC nlohmann_json::nlohmann_json Python3::Python cxxopts::cxxopts)

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
### B Compiler to z80 in C++
44

5-
* The frontend (Lexer, Parser) and first-pass is built with an [easy-to-use LALR(1) grammar and parser generator in python](https://github.com/jahan-addison/xion/tree/master), that interfaces with C++ via libpython or json via `simdjson`
5+
* The frontend (Lexer, Parser) and first-pass is built with an [easy-to-use LALR(1) grammar and parser generator in python](https://github.com/jahan-addison/xion/tree/master), that interfaces with C++ via libpython or json via `nlohmann`
66
* The backend will focus on modern work in SSA, Sea of Nodes, and compiler optimizations through IR breakthroughs in LLVM, gcc, V8, and related toolchains
77

88

@@ -41,7 +41,7 @@ make
4141

4242
Note: These are installed automatically via CPM and cmake.
4343

44-
* `simdjson` - Ultra-performant json parser
44+
* `nlohmann` - JSON for Modern C++
4545
* `cxxopts` - Lightweight commandline option parser
4646

4747
### Resources

roxas/main.cc

+9-7
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <cstdlib>
1818
#include <cxxopts.hpp>
1919
#include <iostream>
20+
#include <nlohmann/json.hpp>
2021
#include <roxas/python_module.h>
2122
#include <roxas/util.h>
2223

@@ -44,7 +45,7 @@ int main(int argc, char** argv)
4445
auto result = options.parse(argc, argv);
4546
auto python_opt = result["python"].as<bool>();
4647

47-
std::string ast_as_json{};
48+
std::string ast_as_json_string{};
4849

4950
if (result.count("help")) {
5051
std::cout
@@ -57,9 +58,12 @@ int main(int argc, char** argv)
5758
}
5859

5960
if (result.count("json")) {
60-
ast_as_json = roxas::util::read_file_from_path(
61+
// If `-j' is passed, load the AST from a pre-compiled JSON on-disk
62+
ast_as_json_string = roxas::util::read_file_from_path(
6163
result["json"].as<std::string>());
6264
} else if (python_opt) {
65+
// Otherwise, use roxas::PythonModuleLoader to compute an AST from
66+
// a source program and a Lexer/Parser in Python (default: Xion)
6367
auto module_args =
6468
result["python-use"].as<std::vector<std::string>>();
6569

@@ -72,7 +76,7 @@ int main(int argc, char** argv)
7276
auto python_module = roxas::PythonModuleLoader(
7377
module_args[1], module_args[0], module_args[3]);
7478

75-
ast_as_json = python_module.call_method_on_module(
79+
ast_as_json_string = python_module.call_method_on_module(
7680
"get_source_program_ast_as_json", { source, "true", "true" });
7781
} else {
7882
std::cerr << "Error :: Invalid arguments try -j <json file> or -p "
@@ -81,10 +85,8 @@ int main(int argc, char** argv)
8185
return EXIT_FAILURE;
8286
}
8387

84-
simdjson::ondemand::parser parser;
85-
auto doc = parser.iterate(ast_as_json);
86-
87-
roxas::util::recursive_print_json(doc);
88+
auto json = nlohmann::json::parse(ast_as_json_string);
89+
std::cout << "AST: " << json.dump() << std::endl;
8890

8991
} catch (std::runtime_error& e) {
9092
std::cerr << "Runtime Exception :: " << e.what() << std::endl;

roxas/symbol.h

+56
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,62 @@
1616

1717
#pragma once
1818

19+
#include <array>
20+
#include <roxas/util.h>
21+
#include <string>
22+
#include <unordered_map>
23+
#include <variant>
24+
1925
namespace roxas {
26+
/**
27+
* @brief Symbol table object
28+
*
29+
* Constructs a symbol table via pass on an AST in simdjson::ondemand::value
30+
* format.
31+
*
32+
* Structure:
33+
*
34+
* Name (LValue)
35+
* \
36+
* \
37+
* ------------------------------------------------------
38+
* | Type | Size | Line Declare | Line Usage | Address |
39+
* ------------------------------------------------------
40+
*/
41+
class Symbol_Table
42+
{
43+
public:
44+
public:
45+
Symbol_Table& operator=(Symbol_Table const&) = delete;
46+
Symbol_Table(Symbol_Table const&) = delete;
47+
48+
using symbol_data = std::array<std::string, 5>;
49+
50+
/**
51+
* @brief Construct a new Symbol_Table object
52+
*
53+
* @param ast simdjson::ondemand::value
54+
*/
55+
explicit Symbol_Table(std::string_view ast);
56+
57+
public:
58+
/**
59+
* @brief Get a symbol by name in the symbol table
60+
*
61+
* @param name
62+
* @return symbol_data
63+
*/
64+
symbol_data get_symbol_by_name(std::string_view name);
65+
/**
66+
* @brief Get a symbol by address in the symbol table
67+
*
68+
* @param name
69+
* @return symbol_data
70+
*/
71+
symbol_data get_symbol_by_address(unsigned int address);
72+
73+
private:
74+
std::unordered_map<std::string, symbol_data> table_;
75+
};
2076

2177
} // namespace roxas

roxas/util.cc

-64
Original file line numberDiff line numberDiff line change
@@ -21,70 +21,6 @@ namespace roxas {
2121

2222
namespace util {
2323

24-
/**
25-
* @brief Recursively print a simdjson::ondemand json element
26-
*
27-
* @param element
28-
*/
29-
void recursive_print_json(simdjson::ondemand::value element)
30-
{
31-
bool add_comma;
32-
switch (element.type()) {
33-
case simdjson::ondemand::json_type::array:
34-
std::cout << "[";
35-
add_comma = false;
36-
for (auto child : element.get_array()) {
37-
if (add_comma) {
38-
std::cout << ",";
39-
}
40-
// We need the call to value() to get
41-
// an simdjson::ondemand::value type.
42-
recursive_print_json(child.value());
43-
add_comma = true;
44-
}
45-
std::cout << "]";
46-
break;
47-
case simdjson::ondemand::json_type::object:
48-
std::cout << "{";
49-
add_comma = false;
50-
for (auto field : element.get_object()) {
51-
if (add_comma) {
52-
std::cout << ",";
53-
}
54-
// key() returns the key as it appears in the raw
55-
// JSON document, if we want the unescaped key,
56-
// we should do field.unescaped_key().
57-
// We could also use field.escaped_key() if we want
58-
// a std::string_view instance, but we do not need
59-
// escaping.
60-
std::cout << "\"" << field.key() << "\": ";
61-
recursive_print_json(field.value());
62-
add_comma = true;
63-
}
64-
std::cout << "}\n";
65-
break;
66-
case simdjson::ondemand::json_type::number:
67-
// assume it fits in a double
68-
std::cout << element.get_double();
69-
break;
70-
case simdjson::ondemand::json_type::string:
71-
// get_string() would return escaped string, but
72-
// we are happy with unescaped string.
73-
std::cout << "\"" << element.get_raw_json_string() << "\"";
74-
break;
75-
case simdjson::ondemand::json_type::boolean:
76-
std::cout << element.get_bool();
77-
break;
78-
case simdjson::ondemand::json_type::null:
79-
// We check that the value is indeed null
80-
// otherwise: an error is thrown.
81-
if (element.is_null()) {
82-
std::cout << "null";
83-
}
84-
break;
85-
}
86-
}
87-
8824
/**
8925
* @brief read source file
9026
*

roxas/util.h

+10-8
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,23 @@
1515
*/
1616

1717
#pragma once
18+
1819
#include <filesystem>
19-
#include <simdjson.h>
2020

2121
namespace roxas {
2222

2323
namespace util {
2424

25-
namespace fs = std::filesystem;
25+
// The overload pattern
26+
template<class... Ts>
27+
struct overload : Ts...
28+
{
29+
using Ts::operator()...;
30+
};
31+
template<class... Ts>
32+
overload(Ts...) -> overload<Ts...>;
2633

27-
/**
28-
* @brief Recursively print a simdjson::ondemand json element
29-
*
30-
* @param element
31-
*/
32-
void recursive_print_json(simdjson::ondemand::value element);
34+
namespace fs = std::filesystem;
3335

3436
/**
3537
* @brief read a file from a fs::path

0 commit comments

Comments
 (0)