Files
wb/wbt/wbt.cpp
T

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);
}
}
};