106 lines
3.0 KiB
C++
106 lines
3.0 KiB
C++
module;
|
|
#include <fstream>
|
|
#include <iostream>
|
|
|
|
// This module is the transpiler from WBT to HTML for site build
|
|
export module wbt;
|
|
|
|
enum WBT_States {
|
|
WBT_STATE_INIT,
|
|
WBT_STATE_OPEN,
|
|
WBT_STATE_EXPRESSION,
|
|
WBT_STATE_CLOSE,
|
|
};
|
|
|
|
struct WBT_Parser_Internal_Data {
|
|
int32_t line = 1;
|
|
int32_t column = 1;
|
|
int32_t expr_start_line = 1;
|
|
int32_t expr_start_column = 1;
|
|
};
|
|
|
|
export class WBT_Parser {
|
|
std::istream& input;
|
|
std::ostream& output;
|
|
public:
|
|
explicit WBT_Parser(
|
|
std::istream& i,
|
|
std::ostream& o
|
|
)
|
|
: input(i), output(o) {
|
|
}
|
|
|
|
void output_char(const char c) const {
|
|
output << c;
|
|
}
|
|
|
|
static void error(const std::string& msg, const int line, const int column) {
|
|
std::cerr << "Error (" << line << "," << column << "): " << msg << std::endl;
|
|
}
|
|
|
|
void eval(const std::string& expr) const {
|
|
output << "[EXPR: " << expr << "]";
|
|
}
|
|
|
|
void parse() const {
|
|
auto state = WBT_STATE_INIT;
|
|
std::string expr;
|
|
auto [line, column, expr_start_line, expr_start_column] = WBT_Parser_Internal_Data();
|
|
while (input.peek() != std::char_traits<char>::eof()) {
|
|
char c;
|
|
input.get(c);
|
|
// State machine
|
|
switch (state) {
|
|
case WBT_STATE_INIT:
|
|
if (c == '{') {
|
|
expr_start_line = line;
|
|
expr_start_column = column;
|
|
state = WBT_STATE_OPEN;
|
|
} else {
|
|
output_char(c);
|
|
}
|
|
break;
|
|
case WBT_STATE_OPEN:
|
|
if (c == '{') {
|
|
state = WBT_STATE_EXPRESSION;
|
|
} else {
|
|
output_char('{');
|
|
output_char(c);
|
|
state = WBT_STATE_INIT;
|
|
}
|
|
break;
|
|
case WBT_STATE_EXPRESSION:
|
|
if (c == '}') {
|
|
state = WBT_STATE_CLOSE;
|
|
} else if (c == '{') {
|
|
error("Invalid character inside of expression", line, column);
|
|
return;
|
|
} else {
|
|
expr += c;
|
|
}
|
|
break;
|
|
case WBT_STATE_CLOSE:
|
|
if (c == '}') {
|
|
eval(expr);
|
|
expr.clear();
|
|
state = WBT_STATE_INIT;
|
|
} else {
|
|
error("Unclosed expression", line, column);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
if (c == '\n') {
|
|
line++;
|
|
column = 1;
|
|
} else {
|
|
column++;
|
|
}
|
|
}
|
|
// Final state cannot be WBT_STATE_EXPRESSION
|
|
if (state == WBT_STATE_EXPRESSION) {
|
|
error("Unclosed expression", expr_start_line, expr_start_column);
|
|
}
|
|
}
|
|
};
|