2024-04-15 22:16:14 +03:00
|
|
|
#include "ccl/rslang/RSParser.h"
|
|
|
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
#pragma warning( push )
|
|
|
|
#pragma warning( disable : 26434 26440 26446 26447 26493 )
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "RSParserImpl.h"
|
|
|
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
#pragma warning( pop )
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
#pragma warning( push )
|
|
|
|
#pragma warning( disable : 26418 26415 26440 )
|
|
|
|
#endif
|
|
|
|
|
2024-05-05 15:11:10 +03:00
|
|
|
#include <optional>
|
|
|
|
|
2024-04-15 22:16:14 +03:00
|
|
|
namespace ccl::rslang::detail {
|
|
|
|
|
|
|
|
RSParser::RSParser(std::optional<ErrorReporter> reporter)
|
|
|
|
: state{ reporter }, impl{ std::make_unique<RSParserImpl>(&state) } {}
|
|
|
|
|
|
|
|
RSParser::~RSParser() = default;
|
|
|
|
RSParser::RSParser(RSParser&& rhs) noexcept = default;
|
|
|
|
RSParser& RSParser::operator=(RSParser&& rhs) noexcept = default;
|
|
|
|
|
|
|
|
bool RSParser::Parse(TokenStream input) {
|
|
|
|
state.NewInput(&input); // Note: using reference to function scoped object
|
|
|
|
const auto success = impl->parse() == 0 && state.countCriticalErrors == 0;
|
|
|
|
if (!success) {
|
|
|
|
if (state.countCriticalErrors == 0) {
|
|
|
|
state.OnError(ParseEID::syntax);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
|
|
int yylex(RawNode* yylval, ParserState* state) {
|
|
|
|
static constexpr auto endParsing = 0;
|
|
|
|
const auto token = (*state->nextTokenCall)();
|
|
|
|
state->currentPosition = token.pos.start;
|
|
|
|
|
|
|
|
if (token.id == TokenID::INTERRUPT) {
|
|
|
|
++state->countCriticalErrors;
|
|
|
|
*yylval = nullptr;
|
|
|
|
return endParsing;
|
|
|
|
} else if (token.id == TokenID::END) {
|
|
|
|
*yylval = nullptr;
|
|
|
|
return endParsing;
|
|
|
|
} else {
|
|
|
|
*yylval = std::make_shared<Node>(token);
|
|
|
|
return static_cast<int>(token.id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void RSParserImpl::error(const std::string& /*msg*/) {}
|
|
|
|
|
|
|
|
RawNode AddNode(const TokenID token, RawNode son) {
|
2024-05-05 15:11:10 +03:00
|
|
|
auto result = std::make_shared<Node>(token, son->token.pos);
|
2024-04-15 22:16:14 +03:00
|
|
|
result->children.emplace_back(son);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
RawNode AddNode(const TokenID token, RawNode son1, RawNode son2) {
|
2024-05-05 15:11:10 +03:00
|
|
|
auto result = std::make_shared<Node>(token, StrRange{ son1->token.pos.start, son2->token.pos.finish });
|
2024-04-15 22:16:14 +03:00
|
|
|
result->children.emplace_back(son1);
|
|
|
|
result->children.emplace_back(son2);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
RawNode BinaryOperation(RawNode op1, RawNode operation, RawNode op2) {
|
|
|
|
operation->token.pos = StrRange{ op1->token.pos.start, op2->token.pos.finish };
|
|
|
|
operation->children.emplace_back(op1);
|
|
|
|
operation->children.emplace_back(op2);
|
|
|
|
return operation;
|
|
|
|
}
|
|
|
|
|
|
|
|
RawNode UnaryOperation(RawNode operation, RawNode operand) {
|
|
|
|
operation->token.pos.finish = operand->token.pos.finish;
|
|
|
|
operation->children.emplace_back(operand);
|
|
|
|
return operation;
|
|
|
|
}
|
|
|
|
|
|
|
|
RawNode RemoveBrackets(RawNode br1, RawNode operand, RawNode br2) {
|
|
|
|
operand->token.pos = StrRange{ br1->token.pos.start, br2->token.pos.finish };
|
2024-05-05 15:11:10 +03:00
|
|
|
auto bracketNode = std::make_shared<Node>(TokenID::PUNC_PL, operand->token.pos);
|
2024-04-15 22:16:14 +03:00
|
|
|
bracketNode->children.emplace_back(operand);
|
|
|
|
return bracketNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
RawNode ReplaceBrackets(const TokenID token, RawNode br1, RawNode argList, RawNode br2) {
|
2024-05-05 15:11:10 +03:00
|
|
|
auto result = std::make_shared<Node>(token, StrRange{ br1->token.pos.start, br2->token.pos.finish });
|
2024-04-15 22:16:14 +03:00
|
|
|
result->children = argList->children;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
RawNode Enumeration(const TokenID token, RawNode el1, RawNode el2) {
|
2024-05-05 15:11:10 +03:00
|
|
|
auto result = std::make_shared<Node>(token, StrRange{ el1->token.pos.start, el2->token.pos.finish });
|
2024-04-15 22:16:14 +03:00
|
|
|
if (el1->token.id != token) {
|
|
|
|
result->children.emplace_back(el1);
|
|
|
|
} else {
|
|
|
|
result->children = el1->children;
|
|
|
|
}
|
|
|
|
if (el2->token.id != token) {
|
|
|
|
result->children.emplace_back(el2);
|
|
|
|
} else {
|
|
|
|
result->children.insert(end(result->children), begin(el2->children), end(el2->children));
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
RawNode Quantifier(RawNode quant, RawNode declaration, RawNode domain, RawNode predicate) {
|
|
|
|
quant->token.pos.finish = predicate->token.pos.finish;
|
|
|
|
quant->children.emplace_back(declaration);
|
|
|
|
quant->children.emplace_back(domain);
|
|
|
|
quant->children.emplace_back(predicate);
|
|
|
|
return quant;
|
|
|
|
}
|
|
|
|
|
2024-05-05 15:11:10 +03:00
|
|
|
RawNode FunctionDeclaration(RawNode start, RawNode argumentsDeclaration, RawNode expr) {
|
2024-04-15 22:16:14 +03:00
|
|
|
auto result = std::make_shared<Node>(
|
2024-05-05 15:11:10 +03:00
|
|
|
TokenID::NT_FUNC_DEFINITION,
|
|
|
|
StrRange{ start->token.pos.start, expr->token.pos.finish }
|
|
|
|
);
|
|
|
|
result->children.emplace_back(argumentsDeclaration);
|
2024-04-15 22:16:14 +03:00
|
|
|
result->children.emplace_back(expr);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
RawNode FunctionCall(RawNode function, RawNode args, RawNode rs) {
|
|
|
|
auto result = std::make_shared<Node>(
|
2024-05-05 15:11:10 +03:00
|
|
|
TokenID::NT_FUNC_CALL,
|
|
|
|
StrRange{ function->token.pos.start, rs->token.pos.finish }
|
|
|
|
);
|
2024-04-15 22:16:14 +03:00
|
|
|
result->children.emplace_back(function);
|
2024-05-05 15:11:10 +03:00
|
|
|
result->children.insert(
|
|
|
|
end(result->children),
|
|
|
|
begin(args->children),
|
|
|
|
end(args->children)
|
|
|
|
);
|
2024-04-15 22:16:14 +03:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
RawNode FilterCall(RawNode filter, RawNode params, RawNode argument, RawNode rp) {
|
|
|
|
filter->token.pos.finish = rp->token.pos.finish;
|
|
|
|
filter->children = params->children;
|
|
|
|
filter->children.emplace_back(argument);
|
|
|
|
return filter;
|
|
|
|
}
|
|
|
|
|
2024-05-05 15:11:10 +03:00
|
|
|
RawNode TextOperator(RawNode operatorName, RawNode args, RawNode rp) {
|
|
|
|
operatorName->token.pos.finish = rp->token.pos.finish;
|
|
|
|
operatorName->children.emplace_back(args);
|
|
|
|
return operatorName;
|
2024-04-15 22:16:14 +03:00
|
|
|
}
|
|
|
|
|
2024-05-05 15:11:10 +03:00
|
|
|
RawNode Decartian(RawNode op1, RawNode decartian, RawNode op2) {
|
2024-04-15 22:16:14 +03:00
|
|
|
if (op1->token.id == TokenID::DECART) {
|
|
|
|
auto result = std::move(op1);
|
|
|
|
result->token.pos.finish = op2->token.pos.finish;
|
|
|
|
result->children.emplace_back(op2);
|
|
|
|
return result;
|
|
|
|
} else {
|
2024-05-05 15:11:10 +03:00
|
|
|
return BinaryOperation(std::move(op1), std::move(decartian), std::move(op2));
|
2024-04-15 22:16:14 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-05 15:11:10 +03:00
|
|
|
RawNode TermDeclaration(
|
|
|
|
RawNode lc,
|
|
|
|
RawNode declaration,
|
|
|
|
RawNode domain,
|
|
|
|
RawNode predicate,
|
|
|
|
RawNode rc
|
|
|
|
) {
|
2024-04-15 22:16:14 +03:00
|
|
|
auto result = std::make_shared<Node>(
|
2024-05-05 15:11:10 +03:00
|
|
|
TokenID::NT_DECLARATIVE_EXPR,
|
|
|
|
StrRange{ lc->token.pos.start, rc->token.pos.finish }
|
|
|
|
);
|
2024-04-15 22:16:14 +03:00
|
|
|
result->children.emplace_back(declaration);
|
|
|
|
result->children.emplace_back(domain);
|
|
|
|
result->children.emplace_back(predicate);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2024-05-05 15:11:10 +03:00
|
|
|
RawNode FullRecursion(
|
|
|
|
RawNode rec,
|
|
|
|
RawNode declaration,
|
|
|
|
RawNode domain,
|
|
|
|
RawNode condition,
|
|
|
|
RawNode iteration,
|
|
|
|
RawNode rc
|
|
|
|
) {
|
2024-04-15 22:16:14 +03:00
|
|
|
auto result = std::make_shared<Node>(
|
2024-05-05 15:11:10 +03:00
|
|
|
TokenID::NT_RECURSIVE_FULL,
|
|
|
|
StrRange{ rec->token.pos.start, rc->token.pos.finish }
|
|
|
|
);
|
|
|
|
result->children.emplace_back(declaration);
|
2024-04-15 22:16:14 +03:00
|
|
|
result->children.emplace_back(domain);
|
|
|
|
result->children.emplace_back(condition);
|
|
|
|
result->children.emplace_back(iteration);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2024-05-05 15:11:10 +03:00
|
|
|
RawNode ShortRecursion(
|
|
|
|
RawNode rec,
|
|
|
|
RawNode declaration,
|
|
|
|
RawNode domain,
|
|
|
|
RawNode iteration,
|
|
|
|
RawNode rc
|
|
|
|
) {
|
2024-04-15 22:16:14 +03:00
|
|
|
auto result = std::make_shared<Node>(
|
2024-05-05 15:11:10 +03:00
|
|
|
TokenID::NT_RECURSIVE_SHORT,
|
|
|
|
StrRange{ rec->token.pos.start, rc->token.pos.finish }
|
|
|
|
);
|
|
|
|
result->children.emplace_back(declaration);
|
2024-04-15 22:16:14 +03:00
|
|
|
result->children.emplace_back(domain);
|
|
|
|
result->children.emplace_back(iteration);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
RawNode Imperative(RawNode imp, RawNode value, RawNode actions, RawNode rc) {
|
|
|
|
auto result = std::make_shared<Node>(
|
2024-05-05 15:11:10 +03:00
|
|
|
TokenID::NT_IMPERATIVE_EXPR,
|
|
|
|
StrRange{ imp->token.pos.start, rc->token.pos.finish }
|
|
|
|
);
|
2024-04-15 22:16:14 +03:00
|
|
|
result->children.emplace_back(value);
|
|
|
|
result->children.insert(end(result->children), begin(actions->children), end(actions->children));
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
SyntaxTree::RawNode CreateNodeRecursive(Node& astNode) {
|
|
|
|
if (astNode.token.id == TokenID::PUNC_PL) {
|
|
|
|
return CreateNodeRecursive(*astNode.children.at(0));
|
|
|
|
} else {
|
|
|
|
auto result = std::make_unique<SyntaxTree::Node>(std::move(astNode.token));
|
|
|
|
for (const auto& child : astNode.children) {
|
|
|
|
result->AdoptChild(CreateNodeRecursive(*child));
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ParserState::CreateSyntaxTree(RawNode root) {
|
|
|
|
parsedTree = std::make_unique<SyntaxTree>(CreateNodeRecursive(*root));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ParserState::FinalizeExpression(RawNode expr) {
|
|
|
|
CreateSyntaxTree(expr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ParserState::FinalizeCstEmpty(RawNode cst, RawNode mode) {
|
|
|
|
mode->token.pos = StrRange{ cst->token.pos.start, mode->token.pos.finish };
|
|
|
|
mode->children.emplace_back(cst);
|
|
|
|
CreateSyntaxTree(mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ParserState::FinalizeCstExpression(RawNode cst, RawNode mode, RawNode data) {
|
|
|
|
mode->token.pos = StrRange{ cst->token.pos.start, data->token.pos.finish };
|
|
|
|
mode->children.emplace_back(cst);
|
|
|
|
mode->children.emplace_back(data);
|
|
|
|
CreateSyntaxTree(mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace ccl::rslang::detail
|
|
|
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
#pragma warning( pop )
|
|
|
|
#endif
|