Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d7b0784

Browse files
Merge pull request #2 from Mikhail158/master
Basic parser implementation
2 parents b5ecd01 + cac78e2 commit d7b0784

File tree

19 files changed

+1704
-0
lines changed

19 files changed

+1704
-0
lines changed

‎.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
build
2+
3+
# IDE Files
4+
.idea
5+
.vs
6+
*.sln
7+
*.vcxproj
8+
*.filters

‎api/engine.cpp

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
#include <cstddef>
2+
#include <iostream>
3+
#include <fstream>
4+
#include <vector>
5+
#include <string>
6+
#include <system_error>
7+
8+
#include "../compiler/parsing/tokenizer.h"
9+
#include "../compiler/parsing/parser.h"
10+
#include "../compiler/parsing/node.h"
11+
#include "../include/engine.h"
12+
13+
14+
namespace olcl
15+
{
16+
namespace
17+
{
18+
void dump_ast(olcl::node & node, std::uint32_t depth, bool escape_next = true)
19+
{
20+
using nt = olcl::node_type;
21+
using nvt = olcl::symbol_type;
22+
23+
switch (node.type)
24+
{
25+
case nt::t_module:
26+
for (auto binding : *node.module.bindings)
27+
{
28+
dump_ast(*binding, depth);
29+
std::cout << "\n";
30+
}
31+
break;
32+
33+
case nt::t_binding:
34+
std::cout << *node.binding.name << " : ";
35+
dump_ast(*node.binding.type, depth, false);
36+
std::cout << " = ";
37+
dump_ast(*node.binding.value, depth, false);
38+
std::cout << ";";
39+
break;
40+
41+
case nt::t_type:
42+
std::cout << *node.typeinfo.name;
43+
break;
44+
45+
case nt::t_value:
46+
switch (node.value.type)
47+
{
48+
case nvt::t_character:
49+
std::cout << '\'' << (char) node.value.character;
50+
break;
51+
case nvt::t_number:
52+
std::cout << *node.value.number;
53+
break;
54+
case nvt::t_string:
55+
std::cout << *node.value.string;
56+
break;
57+
case nvt::t_variable:
58+
std::cout << *node.value.variable;
59+
break;
60+
case nvt::t_function:
61+
if (escape_next) std::cout << '(';
62+
dump_ast(*node.value.function.parameters, depth);
63+
std::cout << " -> ";
64+
dump_ast(*node.value.function.return_type, depth);
65+
std::cout << ' ';
66+
67+
if (node.value.function.code)
68+
dump_ast(*node.value.function.code, depth);
69+
70+
if (escape_next) std::cout << ')';
71+
break;
72+
}
73+
break;
74+
75+
case nt::t_binary_operation:
76+
if (escape_next) std::cout << '(';
77+
dump_ast(*node.binary_operation.left, depth);
78+
std::cout << ' ' << node.binary_operation.operation->representation << ' ';
79+
dump_ast(*node.binary_operation.right, depth);
80+
if (escape_next) std::cout << ')';
81+
break;
82+
83+
case nt::t_unary_operation:
84+
std::cout << '(' << node.unary_operation.operation->representation;
85+
dump_ast(*node.unary_operation.expression, depth);
86+
std::cout << ')';
87+
break;
88+
89+
case nt::t_function_call:
90+
dump_ast(*node.call.expression, depth);
91+
std::cout << '(';
92+
dump_ast(*node.call.arguments, depth, false);
93+
std::cout << ')';
94+
break;
95+
96+
case nt::t_block:
97+
std::cout << "{\n";
98+
99+
for (auto e : *node.block.code)
100+
{
101+
for (std::uint32_t i = 0; i < depth + 1; ++i)
102+
std::cout << " ";
103+
dump_ast(*e, depth + 1u, false);
104+
std::cout << ";\n";
105+
}
106+
107+
for (std::uint32_t i = 0; i < depth; ++i)
108+
std::cout << " ";
109+
std::cout << '}';
110+
break;
111+
112+
case nt::t_list:
113+
if (escape_next) std::cout << '(';
114+
for (auto e : *node.list.values)
115+
{
116+
dump_ast(*e, depth);
117+
std::cout << ", ";
118+
}
119+
if (escape_next) std::cout << ')';
120+
break;
121+
122+
case nt::t_stmt_return:
123+
std::cout << "return ";
124+
dump_ast(*node.stmt_return.expression, depth, false);
125+
break;
126+
127+
case nt::t_stmt_if:
128+
std::cout << "if ";
129+
dump_ast(*node.stmt_if.condition, depth);
130+
std::cout << " then ";
131+
dump_ast(*node.stmt_if.on_true, depth);
132+
133+
if (node.stmt_if.on_false)
134+
{
135+
std::cout << " else ";
136+
dump_ast(*node.stmt_if.on_false, depth);
137+
}
138+
139+
break;
140+
}
141+
}
142+
}
143+
144+
script * engine::loadScript(std::string filename)
145+
{
146+
using isb_char_iter = std::istreambuf_iterator<char>;
147+
148+
std::string data;
149+
try
150+
{
151+
std::ifstream source;
152+
source.exceptions(std::ifstream::failbit | std::ifstream::badbit);
153+
154+
source.open(filename);
155+
data = std::string(isb_char_iter(source), isb_char_iter());
156+
}
157+
catch (std::exception &e)
158+
{
159+
std::cout << "Error #LC001:\n"
160+
<< "File " << filename << " can not be opened" << std::endl;
161+
162+
return nullptr;
163+
}
164+
165+
try
166+
{
167+
auto tokens = olcl::parsing::tokenize(data);
168+
auto ast = olcl::parsing::parse(tokens);
169+
170+
dump_ast(*ast, 0);
171+
auto s = new script(ast);
172+
173+
std::cout << std::flush;
174+
return s;
175+
}
176+
catch (std::runtime_error &e)
177+
{
178+
// fail
179+
return nullptr;
180+
}
181+
}
182+
}

‎api/script.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#include <cassert>
2+
3+
#include "../include/script.h"
4+
#include "../compiler/parsing/node.h"
5+
6+
7+
namespace olcl
8+
{
9+
namespace
10+
{
11+
symbol * val_to_symbol(node * type)
12+
{
13+
if (type->type != node_type::t_value)
14+
{
15+
// TODO: log error?
16+
return nullptr;
17+
}
18+
19+
return &type->value;
20+
}
21+
}
22+
23+
script::script(olcl::node * ast_)
24+
: code(ast_)
25+
{
26+
assert(ast_ != nullptr);
27+
assert(ast_->type == node_type::t_module);
28+
}
29+
30+
symbol * script::findSymbol(std::string id) const
31+
{
32+
for (auto b : *code->module.bindings)
33+
{
34+
if (*b->binding.name == id)
35+
return val_to_symbol(b->binding.value);
36+
}
37+
38+
return nullptr;
39+
}
40+
}

‎build.sh

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#!/bin/bash
2+
3+
# settings
4+
CPP_VERSION=11
5+
BUILD_DIR_DEBUG=./build/debug
6+
BUILD_DIR_RELEASE=./build/release
7+
8+
RELEASE_PARAMS="-fPIC -shared -Wl,--whole-archive -Wl,--no-whole-archive -std=c++$CPP_VERSION -O2 -s"
9+
DEBUG_PARAMS="-fPIC -shared -Wl,--whole-archive -Wl,--no-whole-archive -std=c++$CPP_VERSION -Wall -Wextra -pedantic"
10+
11+
COMPILER_LINUX="g++"
12+
COMPILER_WINDOWS="x86_64-w64-mingw32-g++.exe"
13+
14+
SOURCE_FILES="api/engine.cpp api/script.cpp compiler/parsing/token.cpp compiler/parsing/operators.cpp compiler/parsing/tokenizer.cpp compiler/parsing/parser.cpp compiler/error_handler.cpp"
15+
16+
# prepare folders
17+
mkdir -p $BUILD_DIR_DEBUG
18+
mkdir -p $BUILD_DIR_RELEASE
19+
20+
21+
PLATFORMS=(${2//#/ })
22+
23+
if [[ "1ドル" = "debug" ]]; then
24+
printf "Configuring the debug build mode"
25+
DIR="$BUILD_DIR_DEBUG"
26+
PARAMS="$DEBUG_PARAMS"
27+
elif [[ "1ドル" = "release" ]]; then
28+
printf "Configuring the release build mode"
29+
DIR="$BUILD_DIR_RELEASE"
30+
PARAMS="$RELEASE_PARAMS"
31+
else
32+
echo "Usage: ./build.sh [debug|release] [platforms; ...]"
33+
exit 1
34+
fi
35+
36+
for platform in "${PLATFORMS[@]}"; do
37+
printf "\n\nPreparing to compile code targeting $platform...\n"
38+
39+
if [[ "$platform" = "windows" ]]; then
40+
COMPILER="$COMPILER_WINDOWS"
41+
FILENAME="$DIR/win_olcl"
42+
elif [[ "$platform" = "linux" ]]; then
43+
COMPILER="$COMPILER_LINUX"
44+
FILENAME="$DIR/lin_olcl"
45+
else
46+
echo "Supported target platforms: windows, linux"
47+
exit 2
48+
fi
49+
50+
printf "Running command: $COMPILER $SOURCE_FILES $PARAMS -o $FILENAME.so\n\n"
51+
eval "$COMPILER $SOURCE_FILES $PARAMS -o $FILENAME.so"
52+
# eval "ar rvs $FILENAME.a $FILENAME.so"
53+
done

‎compiler/error.h

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#pragma once
2+
3+
namespace olcl { namespace parsing {
4+
enum class error_t
5+
{
6+
// Empty
7+
c_no_errors = 0,
8+
9+
10+
// Start up
11+
c_file_not_exists = 1,
12+
13+
14+
// Tokenization
15+
t_unexpected_eof = 10,
16+
17+
t_invalid_identifier = 20,
18+
19+
t_invalid_compiler_directive_name = 21,
20+
t_compiler_directive_name_not_stated = 22,
21+
22+
t_special_character_not_exists = 30,
23+
t_misleading_character = 31,
24+
25+
26+
// Parsing
27+
p_identifier_expected = 100,
28+
p_method_type_expected = 101,
29+
p_method_name_expected = 102,
30+
p_opening_brace_expected = 103,
31+
32+
p_duplicated_modifier = 110,
33+
p_reference_can_not_be_constant = 111,
34+
p_array_can_not_contain_references = 112,
35+
36+
p_colon_before_type_specefication_expected = 120,
37+
p_double_colon_expected = 121,
38+
39+
p_unknown_unit = 130,
40+
p_closing_brace_expected = 131,
41+
42+
p_value_expected = 140,
43+
p_equal_sign_expected = 141,
44+
45+
p_function_vertical_bar_after_type_expected = 150,
46+
p_function_vertical_bar_after_params_expected = 151,
47+
48+
49+
50+
// Optimization
51+
// ...
52+
53+
54+
// Translation
55+
// ...
56+
57+
58+
// Compilation
59+
// ...
60+
61+
62+
// Special
63+
s_not_implemented = 1000,
64+
};
65+
}}

‎compiler/error_handler.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include <iostream>
2+
3+
#include "error_handler.h"
4+
#include "parsing/tokenizer.h"
5+
#include "parsing/parser.h"
6+
7+
8+
namespace olcl
9+
{
10+
template <typename T>
11+
static inline void log_error_common(T state)
12+
{
13+
std::cout << "Error #LC" << static_cast<int>(state.error.code) << ":\n";
14+
std::cout << state.error.message << "\n\n";
15+
}
16+
17+
void log_error(parsing::tokenizer::state state)
18+
{
19+
log_error_common(state);
20+
21+
std::cout << "Line: " << state.line << "\n";
22+
std::cout << "Column: " << state.column << "\n\n";
23+
24+
throw std::runtime_error("halt");
25+
}
26+
27+
void log_error(parsing::parser::state state)
28+
{
29+
log_error_common(state);
30+
31+
std::cout << "Line: " << state.peek().line << "\n";
32+
std::cout << "Column: " << state.peek().column << "\n\n";
33+
// TODO: Implement specific error handling stuff
34+
// TODO: Implement specific error handling stuff
35+
// TODO: Implement specific error handling stuff
36+
throw std::runtime_error("halt");
37+
}
38+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /