162 lines
9.7 KiB
C++
162 lines
9.7 KiB
C++
#pragma once
|
|
#include <string>
|
|
#include <vector>
|
|
#include <map>
|
|
#include <set>
|
|
#include <utility>
|
|
|
|
struct ChildRule {
|
|
std::vector<std::string> allowedConcepts;
|
|
bool isSingleValued = false; // false = multi-valued (list), true = single-valued (pointer)
|
|
};
|
|
|
|
class ASTSchema {
|
|
public:
|
|
ASTSchema() {
|
|
initializeSchema();
|
|
}
|
|
|
|
// Check if a child concept is allowed under a parent concept in a specific role
|
|
bool isLegalChild(const std::string& parentConcept, const std::string& role, const std::string& childConcept) const {
|
|
auto parentIt = schema_.find(parentConcept);
|
|
if (parentIt == schema_.end()) {
|
|
return false; // Parent concept not in schema
|
|
}
|
|
|
|
auto roleIt = parentIt->second.find(role);
|
|
if (roleIt == parentIt->second.end()) {
|
|
return false; // Role not defined for this parent
|
|
}
|
|
|
|
const ChildRule& rule = roleIt->second;
|
|
|
|
// Check if the child concept is in the allowed list
|
|
for (const auto& allowedConcept : rule.allowedConcepts) {
|
|
if (allowedConcept == childConcept) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Get the cardinality of a role (single vs multi-valued)
|
|
bool isSingleValued(const std::string& parentConcept, const std::string& role) const {
|
|
auto parentIt = schema_.find(parentConcept);
|
|
if (parentIt == schema_.end()) {
|
|
return false; // Parent concept not in schema
|
|
}
|
|
|
|
auto roleIt = parentIt->second.find(role);
|
|
if (roleIt == parentIt->second.end()) {
|
|
return false; // Role not defined for this parent
|
|
}
|
|
|
|
return roleIt->second.isSingleValued;
|
|
}
|
|
|
|
// Get allowed child concepts for a role
|
|
std::vector<std::string> getAllowedConcepts(const std::string& parentConcept, const std::string& role) const {
|
|
std::vector<std::string> result;
|
|
auto parentIt = schema_.find(parentConcept);
|
|
if (parentIt == schema_.end()) {
|
|
return result; // Empty if parent not found
|
|
}
|
|
|
|
auto roleIt = parentIt->second.find(role);
|
|
if (roleIt == parentIt->second.end()) {
|
|
return result; // Empty if role not found
|
|
}
|
|
|
|
return roleIt->second.allowedConcepts;
|
|
}
|
|
|
|
private:
|
|
std::map<std::string, std::map<std::string, ChildRule>> schema_;
|
|
|
|
void initializeSchema() {
|
|
// Module concept rules
|
|
addRule("Module", "functions", {"Function"}, false); // multi-valued
|
|
addRule("Module", "variables", {"Variable"}, false); // multi-valued
|
|
addRule("Module", "targetLanguage", {}, true); // property, not used for AST nodes
|
|
addRule("Module", "annotations", {"DerefStrategy", "OptimizationLock", "LangSpecific"}, false); // multi-valued
|
|
|
|
// Function concept rules
|
|
addRule("Function", "parameters", {"Parameter"}, false); // multi-valued
|
|
addRule("Function", "returnType", {"PrimitiveType", "ListType", "SetType", "MapType", "TupleType", "ArrayType", "OptionalType", "CustomType"}, true); // single-valued
|
|
addRule("Function", "body", {"Block", "Assignment", "IfStatement", "WhileLoop", "ForLoop", "Return", "ExpressionStatement"}, false); // multi-valued
|
|
addRule("Function", "annotations", {"DerefStrategy", "OptimizationLock", "LangSpecific"}, false); // multi-valued
|
|
|
|
// Parameter concept rules
|
|
addRule("Parameter", "type", {"PrimitiveType", "ListType", "SetType", "MapType", "TupleType", "ArrayType", "OptionalType", "CustomType"}, true); // single-valued
|
|
addRule("Parameter", "defaultValue", {"IntegerLiteral", "FloatLiteral", "StringLiteral", "BooleanLiteral", "NullLiteral", "ListLiteral", "BinaryOperation", "UnaryOperation", "FunctionCall", "VariableReference"}, true); // single-valued
|
|
|
|
// Variable concept rules
|
|
addRule("Variable", "type", {"PrimitiveType", "ListType", "SetType", "MapType", "TupleType", "ArrayType", "OptionalType", "CustomType"}, true); // single-valued
|
|
addRule("Variable", "initializer", {"IntegerLiteral", "FloatLiteral", "StringLiteral", "BooleanLiteral", "NullLiteral", "ListLiteral", "BinaryOperation", "UnaryOperation", "FunctionCall", "VariableReference"}, true); // single-valued
|
|
addRule("Variable", "annotations", {"DerefStrategy", "OptimizationLock", "LangSpecific"}, false); // multi-valued
|
|
|
|
// Block concept rules
|
|
addRule("Block", "statements", {"Assignment", "IfStatement", "WhileLoop", "ForLoop", "Return", "ExpressionStatement"}, false); // multi-valued
|
|
|
|
// Assignment concept rules
|
|
addRule("Assignment", "target", {"VariableReference"}, true); // single-valued
|
|
addRule("Assignment", "value", {"IntegerLiteral", "FloatLiteral", "StringLiteral", "BooleanLiteral", "NullLiteral", "ListLiteral", "BinaryOperation", "UnaryOperation", "FunctionCall", "VariableReference", "IndexAccess", "MemberAccess"}, true); // single-valued
|
|
|
|
// IfStatement concept rules
|
|
addRule("IfStatement", "condition", {"BinaryOperation", "UnaryOperation", "FunctionCall", "VariableReference", "IntegerLiteral", "FloatLiteral", "StringLiteral", "BooleanLiteral", "NullLiteral"}, true); // single-valued
|
|
addRule("IfStatement", "thenBranch", {"Block", "Assignment", "IfStatement", "WhileLoop", "ForLoop", "Return", "ExpressionStatement"}, false); // multi-valued
|
|
addRule("IfStatement", "elseBranch", {"Block", "Assignment", "IfStatement", "WhileLoop", "ForLoop", "Return", "ExpressionStatement"}, false); // multi-valued
|
|
|
|
// WhileLoop concept rules
|
|
addRule("WhileLoop", "condition", {"BinaryOperation", "UnaryOperation", "FunctionCall", "VariableReference", "IntegerLiteral", "FloatLiteral", "StringLiteral", "BooleanLiteral", "NullLiteral"}, true); // single-valued
|
|
addRule("WhileLoop", "body", {"Block", "Assignment", "IfStatement", "WhileLoop", "ForLoop", "Return", "ExpressionStatement"}, false); // multi-valued
|
|
|
|
// ForLoop concept rules
|
|
addRule("ForLoop", "iteratorName", {}, true); // property, not used for AST nodes
|
|
addRule("ForLoop", "iterable", {"VariableReference", "FunctionCall", "BinaryOperation", "UnaryOperation", "ListLiteral"}, true); // single-valued
|
|
addRule("ForLoop", "body", {"Block", "Assignment", "IfStatement", "WhileLoop", "ForLoop", "Return", "ExpressionStatement"}, false); // multi-valued
|
|
|
|
// Return concept rules
|
|
addRule("Return", "value", {"IntegerLiteral", "FloatLiteral", "StringLiteral", "BooleanLiteral", "NullLiteral", "ListLiteral", "BinaryOperation", "UnaryOperation", "FunctionCall", "VariableReference", "IndexAccess", "MemberAccess"}, true); // single-valued
|
|
|
|
// ExpressionStatement concept rules
|
|
addRule("ExpressionStatement", "expression", {"BinaryOperation", "UnaryOperation", "FunctionCall", "VariableReference", "IntegerLiteral", "FloatLiteral", "StringLiteral", "BooleanLiteral", "NullLiteral", "ListLiteral", "IndexAccess", "MemberAccess"}, true); // single-valued
|
|
|
|
// BinaryOperation concept rules
|
|
addRule("BinaryOperation", "left", {"IntegerLiteral", "FloatLiteral", "StringLiteral", "BooleanLiteral", "NullLiteral", "ListLiteral", "BinaryOperation", "UnaryOperation", "FunctionCall", "VariableReference", "IndexAccess", "MemberAccess"}, true); // single-valued
|
|
addRule("BinaryOperation", "right", {"IntegerLiteral", "FloatLiteral", "StringLiteral", "BooleanLiteral", "NullLiteral", "ListLiteral", "BinaryOperation", "UnaryOperation", "FunctionCall", "VariableReference", "IndexAccess", "MemberAccess"}, true); // single-valued
|
|
|
|
// UnaryOperation concept rules
|
|
addRule("UnaryOperation", "operand", {"IntegerLiteral", "FloatLiteral", "StringLiteral", "BooleanLiteral", "NullLiteral", "ListLiteral", "BinaryOperation", "UnaryOperation", "FunctionCall", "VariableReference", "IndexAccess", "MemberAccess"}, true); // single-valued
|
|
|
|
// FunctionCall concept rules
|
|
addRule("FunctionCall", "functionName", {}, true); // property, not used for AST nodes
|
|
addRule("FunctionCall", "arguments", {"IntegerLiteral", "FloatLiteral", "StringLiteral", "BooleanLiteral", "NullLiteral", "ListLiteral", "BinaryOperation", "UnaryOperation", "FunctionCall", "VariableReference", "IndexAccess", "MemberAccess"}, false); // multi-valued
|
|
|
|
// VariableReference concept rules
|
|
addRule("VariableReference", "variableName", {}, true); // property, not used for AST nodes
|
|
|
|
// ListLiteral concept rules
|
|
addRule("ListLiteral", "elements", {"IntegerLiteral", "FloatLiteral", "StringLiteral", "BooleanLiteral", "NullLiteral", "ListLiteral", "BinaryOperation", "UnaryOperation", "FunctionCall", "VariableReference", "IndexAccess", "MemberAccess"}, false); // multi-valued
|
|
|
|
// IndexAccess concept rules
|
|
addRule("IndexAccess", "target", {"VariableReference", "FunctionCall", "IndexAccess", "MemberAccess"}, true); // single-valued
|
|
addRule("IndexAccess", "index", {"IntegerLiteral", "VariableReference", "BinaryOperation", "FunctionCall"}, true); // single-valued
|
|
|
|
// MemberAccess concept rules
|
|
addRule("MemberAccess", "target", {"VariableReference", "FunctionCall", "IndexAccess", "MemberAccess"}, true); // single-valued
|
|
addRule("MemberAccess", "memberName", {}, true); // property, not used for AST nodes
|
|
|
|
// Type concepts - no child rules needed as they're leaf nodes for types
|
|
|
|
// Annotation concepts - no child rules needed as they're leaf nodes for annotations
|
|
}
|
|
|
|
void addRule(const std::string& parentConcept, const std::string& role, const std::vector<std::string>& allowedConcepts, bool isSingleValued) {
|
|
ChildRule rule;
|
|
rule.allowedConcepts = allowedConcepts;
|
|
rule.isSingleValued = isSingleValued;
|
|
schema_[parentConcept][role] = rule;
|
|
}
|
|
}; |