Basic refactor
This commit is contained in:
1 parent
aac972c6ca
commit
0c4afe87d9
89 files changed
+7106
-6768
No files matched your search
@@ -1,4 +1,4 @@
|
||||
#include "astnode.h"
|
||||
#include "ast_nodes.h"
|
||||
|
||||
/*************************** AST NODE ********************************/
|
||||
|
||||
@@ -6,17 +6,17 @@ AstNode::~AstNode() = default;
|
||||
|
||||
/*************************** NUMBER NODE ********************************/
|
||||
|
||||
NumberNode::NumberNode(const std::string& expression) {
|
||||
if(expression.size() > 2) {
|
||||
if(expression.substr(0, 2) == "0x") {
|
||||
this->value = std::stoll(expression, 0, 16);
|
||||
} else if(expression.substr(0, 2) == "0b") {
|
||||
this->value = std::stoll(expression, 0, 2);
|
||||
NumberNode::NumberNode(const std::string &expression) {
|
||||
if (expression.size() > 2) {
|
||||
if (expression.substr(0, 2) == "0x") {
|
||||
this->value = std::stoll(expression, nullptr, 16);
|
||||
} else if (expression.substr(0, 2) == "0b") {
|
||||
this->value = std::stoll(expression, nullptr, 2);
|
||||
} else {
|
||||
this->value = std::stoll(expression, 0, 10);
|
||||
this->value = std::stoll(expression, nullptr, 10);
|
||||
}
|
||||
} else {
|
||||
this->value = std::stoll(expression, 0, 10);
|
||||
this->value = std::stoll(expression, nullptr, 10);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,28 +29,28 @@ std::string StringNode::asString() {
|
||||
/*************************** VALUE NODE ********************************/
|
||||
|
||||
long long ValueNode::asInt() {
|
||||
if(is(INT)) {
|
||||
if (is(INT)) {
|
||||
return intValue.value();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string ValueNode::asString() {
|
||||
if(is(STRING)) {
|
||||
if (is(STRING)) {
|
||||
return stringValue.value();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string ValueNode::asIdentifier() {
|
||||
if(is(IDENTIFIER) || is(WIRE)) {
|
||||
if (is(IDENTIFIER) || is(WIRE)) {
|
||||
return identifierValue.value();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
bool ValueNode::asBool() {
|
||||
if(is(BOOL)) {
|
||||
if (is(BOOL)) {
|
||||
return boolValue.value();
|
||||
}
|
||||
return false;
|
||||
@@ -2,8 +2,9 @@
|
||||
#define AST_NODE_H
|
||||
|
||||
#include "token.h"
|
||||
#include "sourceerror.h"
|
||||
#include "source_error.h"
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
@@ -19,58 +20,60 @@ public:
|
||||
|
||||
virtual ~AstNode();
|
||||
|
||||
AstNode(AstNode&&) = default;
|
||||
AstNode& operator=(AstNode&&) = default;
|
||||
AstNode(const AstNode&) = default;
|
||||
AstNode& operator=(const AstNode&) = default;
|
||||
AstNode(AstNode &&) = default;
|
||||
|
||||
AstNode &operator=(AstNode &&) = default;
|
||||
|
||||
AstNode(const AstNode &) = default;
|
||||
|
||||
AstNode &operator=(const AstNode &) = default;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct EnumNode: public AstNode
|
||||
{
|
||||
template<typename T>
|
||||
struct EnumNode : public AstNode {
|
||||
EnumNode() = default;
|
||||
explicit EnumNode(T value): value(value) {}
|
||||
|
||||
explicit EnumNode(T value) : value(value) {}
|
||||
|
||||
T value;
|
||||
};
|
||||
|
||||
struct StringNode: public AstNode
|
||||
{
|
||||
struct StringNode : public AstNode {
|
||||
std::string value;
|
||||
|
||||
std::string asString();
|
||||
};
|
||||
|
||||
struct IdentifierNode: public AstNode
|
||||
{
|
||||
struct IdentifierNode : public AstNode {
|
||||
std::string value;
|
||||
};
|
||||
|
||||
struct NumberNode: public AstNode {
|
||||
struct NumberNode : public AstNode {
|
||||
long long int value;
|
||||
explicit NumberNode(const std::string& expression);
|
||||
NumberNode(): value(0) {}
|
||||
|
||||
explicit NumberNode(const std::string &expression);
|
||||
|
||||
NumberNode() : value(0) {}
|
||||
};
|
||||
|
||||
|
||||
struct CountNode: public AstNode
|
||||
{
|
||||
struct CountNode : public AstNode {
|
||||
NumberNode first;
|
||||
NumberNode second;
|
||||
|
||||
CountNode(NumberNode first, NumberNode second): first(first), second(second) {}
|
||||
CountNode(NumberNode first, NumberNode second) : first(std::move(first)), second(std::move(second)) {}
|
||||
|
||||
CountNode() = default;
|
||||
};
|
||||
|
||||
|
||||
struct AddressSpaceNode: public AstNode
|
||||
{
|
||||
struct AddressSpaceNode : public AstNode {
|
||||
IdentifierNode name;
|
||||
NumberNode start;
|
||||
NumberNode end;
|
||||
};
|
||||
|
||||
class ValueNode: public AstNode
|
||||
{
|
||||
class ValueNode : public AstNode {
|
||||
public:
|
||||
enum ValueType {
|
||||
INT,
|
||||
@@ -92,33 +95,42 @@ private:
|
||||
public:
|
||||
ValueNode() = default;
|
||||
|
||||
ValueType getType() {
|
||||
ValueType getType() const {
|
||||
return type.value;
|
||||
}
|
||||
|
||||
long long asInt();
|
||||
|
||||
std::string asString();
|
||||
|
||||
std::string asIdentifier();
|
||||
|
||||
bool asBool();
|
||||
|
||||
bool is(ValueType valueType);
|
||||
|
||||
static ValueNode ofBool(bool _value);
|
||||
|
||||
static ValueNode ofInt(long long _value);
|
||||
|
||||
static ValueNode ofString(std::string _value);
|
||||
|
||||
static ValueNode ofIdentifier(std::string _value);
|
||||
|
||||
static ValueNode ofMemory(std::optional<std::string> _value);
|
||||
|
||||
static ValueNode ofNull();
|
||||
|
||||
static ValueNode ofWire(std::optional<std::string> _value);
|
||||
};
|
||||
|
||||
struct ConditionNode
|
||||
{
|
||||
struct ConditionNode {
|
||||
bool negated;
|
||||
IdentifierNode functionName;
|
||||
std::vector<ValueNode> params;
|
||||
};
|
||||
|
||||
class ActionNode: public AstNode {
|
||||
class ActionNode : public AstNode {
|
||||
public:
|
||||
enum ActionType {
|
||||
ERROR,
|
||||
@@ -130,25 +142,21 @@ public:
|
||||
};
|
||||
|
||||
|
||||
struct IfStatementNode: public AstNode
|
||||
{
|
||||
struct IfStatementNode : public AstNode {
|
||||
ConditionNode condition;
|
||||
ActionNode action;
|
||||
};
|
||||
|
||||
struct RuleNode: public AstNode
|
||||
{
|
||||
struct RuleNode : public AstNode {
|
||||
std::vector<IfStatementNode> statements;
|
||||
};
|
||||
|
||||
struct EnumerationNode: public AstNode
|
||||
{
|
||||
struct EnumerationNode : public AstNode {
|
||||
StringNode key;
|
||||
ValueNode value;
|
||||
};
|
||||
|
||||
struct PopupNode: public AstNode
|
||||
{
|
||||
struct PopupNode : public AstNode {
|
||||
enum PopupType {
|
||||
AUTOMATIC,
|
||||
ON_DEMAND
|
||||
@@ -164,24 +172,22 @@ struct PopupNode: public AstNode
|
||||
std::vector<RuleNode> rules;
|
||||
};
|
||||
|
||||
struct PropertyNode: public AstNode
|
||||
{
|
||||
struct PropertyNode : public AstNode {
|
||||
IdentifierNode key;
|
||||
ValueNode value;
|
||||
};
|
||||
|
||||
struct DisplayItemNode: public AstNode
|
||||
{
|
||||
struct DisplayItemNode : public AstNode {
|
||||
IdentifierNode type;
|
||||
std::vector<PropertyNode> values;
|
||||
|
||||
long long int asInt(std::vector<SourceError>* errors, const std::string& property, long long int _default = 0) {
|
||||
for(auto& prop: values) {
|
||||
if(prop.key.value == property) {
|
||||
if(prop.value.is(ValueNode::INT)) {
|
||||
long long int asInt(std::vector<SourceError> *errors, const std::string &property, long long int _default = 0) {
|
||||
for (auto &prop: values) {
|
||||
if (prop.key.value == property) {
|
||||
if (prop.value.is(ValueNode::INT)) {
|
||||
return prop.value.asInt();
|
||||
} else {
|
||||
if(errors != nullptr) {
|
||||
if (errors != nullptr) {
|
||||
errors->emplace_back(prop.value.span, "expected number");
|
||||
}
|
||||
}
|
||||
@@ -190,13 +196,13 @@ struct DisplayItemNode: public AstNode
|
||||
return _default;
|
||||
}
|
||||
|
||||
std::string asIdentifier(std::vector<SourceError>* errors, const std::string& property, std::string _default = "") {
|
||||
for(auto& prop: values) {
|
||||
if(prop.key.value == property) {
|
||||
if(prop.value.is(ValueNode::IDENTIFIER)) {
|
||||
std::string asIdentifier(std::vector<SourceError> *errors, const std::string &property, std::string _default = "") {
|
||||
for (auto &prop: values) {
|
||||
if (prop.key.value == property) {
|
||||
if (prop.value.is(ValueNode::IDENTIFIER)) {
|
||||
return prop.value.asIdentifier();
|
||||
} else {
|
||||
if(errors != nullptr) {
|
||||
if (errors != nullptr) {
|
||||
errors->emplace_back(prop.value.span, "expected identifier");
|
||||
}
|
||||
}
|
||||
@@ -206,13 +212,13 @@ struct DisplayItemNode: public AstNode
|
||||
}
|
||||
|
||||
|
||||
std::string asString(std::vector<SourceError>* errors, const std::string& property, std::string _default = "") {
|
||||
for(auto& prop: values) {
|
||||
if(prop.key.value == property) {
|
||||
if(prop.value.is(ValueNode::STRING)) {
|
||||
std::string asString(std::vector<SourceError> *errors, const std::string &property, std::string _default = "") {
|
||||
for (auto &prop: values) {
|
||||
if (prop.key.value == property) {
|
||||
if (prop.value.is(ValueNode::STRING)) {
|
||||
return prop.value.asString();
|
||||
} else {
|
||||
if(errors != nullptr) {
|
||||
if (errors != nullptr) {
|
||||
errors->emplace_back(prop.value.span, "expected string");
|
||||
}
|
||||
}
|
||||
@@ -222,13 +228,11 @@ struct DisplayItemNode: public AstNode
|
||||
}
|
||||
};
|
||||
|
||||
struct DisplayNode: public AstNode
|
||||
{
|
||||
struct DisplayNode : public AstNode {
|
||||
std::vector<DisplayItemNode> items;
|
||||
};
|
||||
|
||||
struct PinConnectionNode: public AstNode
|
||||
{
|
||||
struct PinConnectionNode : public AstNode {
|
||||
enum ConnectionType {
|
||||
REQUIRED,
|
||||
OPTIONAL
|
||||
@@ -238,8 +242,7 @@ struct PinConnectionNode: public AstNode
|
||||
EnumNode<ConnectionType> type;
|
||||
};
|
||||
|
||||
struct PinNode: public AstNode
|
||||
{
|
||||
struct PinNode : public AstNode {
|
||||
enum PinType {
|
||||
IN_OUT,
|
||||
IN,
|
||||
@@ -254,8 +257,7 @@ struct PinNode: public AstNode
|
||||
std::optional<std::vector<ValueNode>> wires;
|
||||
};
|
||||
|
||||
struct WireNode: public AstNode
|
||||
{
|
||||
struct WireNode : public AstNode {
|
||||
enum WireType {
|
||||
WIRE,
|
||||
WIRED_AND,
|
||||
@@ -272,22 +274,19 @@ struct WireNode: public AstNode
|
||||
ValueNode terminateWith;
|
||||
};
|
||||
|
||||
struct AttributeNode: public AstNode
|
||||
{
|
||||
struct AttributeNode : public AstNode {
|
||||
ValueNode::ValueType type;
|
||||
IdentifierNode name;
|
||||
std::optional<ValueNode> defaultValue;
|
||||
std::optional<PopupNode> popup;
|
||||
};
|
||||
|
||||
struct ConnectionComponentNode: public AstNode
|
||||
{
|
||||
struct ConnectionComponentNode : public AstNode {
|
||||
IdentifierNode component;
|
||||
IdentifierNode pin;
|
||||
};
|
||||
|
||||
struct ConnectionNode: public AstNode
|
||||
{
|
||||
struct ConnectionNode : public AstNode {
|
||||
ConnectionComponentNode first;
|
||||
std::optional<ConnectionComponentNode> second;
|
||||
|
||||
@@ -298,8 +297,7 @@ struct ConnectionNode: public AstNode
|
||||
std::optional<std::vector<ValueNode>> secondWires;
|
||||
};
|
||||
|
||||
struct ComponentNode: public AstNode
|
||||
{
|
||||
struct ComponentNode : public AstNode {
|
||||
enum ComponentType {
|
||||
OTHER,
|
||||
PROCESSOR,
|
||||
@@ -318,8 +316,7 @@ struct ComponentNode: public AstNode
|
||||
std::vector<AttributeNode> attributes;
|
||||
};
|
||||
|
||||
struct BusNode: public AstNode
|
||||
{
|
||||
struct BusNode : public AstNode {
|
||||
enum BusType {
|
||||
AUTOMATIC,
|
||||
REGULAR,
|
||||
@@ -335,8 +332,7 @@ struct BusNode: public AstNode
|
||||
std::vector<WireNode> wires;
|
||||
};
|
||||
|
||||
struct LibraryNode: public AstNode
|
||||
{
|
||||
struct LibraryNode : public AstNode {
|
||||
std::optional<StringNode> name;
|
||||
std::optional<StringNode> libraryInfo;
|
||||
std::optional<StringNode> header;
|
||||
@@ -353,14 +349,12 @@ struct LibraryNode: public AstNode
|
||||
};
|
||||
|
||||
// SCHEMA models
|
||||
struct InstanceAttributeNode: public AstNode
|
||||
{
|
||||
struct InstanceAttributeNode : public AstNode {
|
||||
IdentifierNode name;
|
||||
ValueNode value;
|
||||
};
|
||||
|
||||
struct InstanceNode: public AstNode
|
||||
{
|
||||
struct InstanceNode : public AstNode {
|
||||
IdentifierNode name;
|
||||
IdentifierNode component;
|
||||
|
||||
@@ -370,14 +364,12 @@ struct InstanceNode: public AstNode
|
||||
std::optional<NumberNode> size;
|
||||
};
|
||||
|
||||
struct ConnectionComponentInstance: public AstNode
|
||||
{
|
||||
struct ConnectionComponentInstance : public AstNode {
|
||||
IdentifierNode instance;
|
||||
IdentifierNode pin;
|
||||
};
|
||||
|
||||
struct ConnectionInstanceNode: public AstNode
|
||||
{
|
||||
struct ConnectionInstanceNode : public AstNode {
|
||||
ConnectionComponentInstance first;
|
||||
std::optional<ConnectionComponentInstance> second;
|
||||
|
||||
@@ -387,8 +379,7 @@ struct ConnectionInstanceNode: public AstNode
|
||||
};
|
||||
|
||||
|
||||
struct SchemaNode: public AstNode
|
||||
{
|
||||
struct SchemaNode : public AstNode {
|
||||
std::optional<StringNode> source;
|
||||
|
||||
std::vector<InstanceNode> instances;
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,10 +1,10 @@
|
||||
#ifndef COMDEL_PARSER_H
|
||||
#define COMDEL_PARSER_H
|
||||
|
||||
#include "sourceerror.h"
|
||||
#include "source_error.h"
|
||||
#include "presult.h"
|
||||
#include "token.h"
|
||||
#include "astnode.h"
|
||||
#include "ast_nodes.h"
|
||||
|
||||
#include <optional>
|
||||
#include <set>
|
||||
@@ -18,23 +18,21 @@
|
||||
class Spanner {
|
||||
// REFERENCE to the parser's prevSpan. After parsing a node this will
|
||||
// "point" to the span of the last token contained in the node.
|
||||
const Span& prevSpan;
|
||||
const Span &prevSpan;
|
||||
|
||||
public:
|
||||
const Span lo; // the low end of the span, beginning of the node
|
||||
|
||||
Spanner(Span lo, Span &prevSpan) : lo(lo), prevSpan(prevSpan) {}
|
||||
|
||||
Spanner(Span lo, Span& prevSpan) : lo(lo), prevSpan(prevSpan) {}
|
||||
|
||||
template <typename T, typename = std::enable_if<std::is_base_of<AstNode, T>::value>>
|
||||
typename std::remove_reference_t<T> operator()(T&& astNode) const {
|
||||
template<typename T, typename = std::enable_if<std::is_base_of<AstNode, T>::value>>
|
||||
typename std::remove_reference_t<T> operator()(T &&astNode) const {
|
||||
astNode.span = lo.to(prevSpan);
|
||||
return std::move(astNode);
|
||||
return std::forward<T>(astNode);
|
||||
}
|
||||
};
|
||||
|
||||
class ComdelParser
|
||||
{
|
||||
class ComdelParser {
|
||||
private:
|
||||
std::vector<Token> tokens;
|
||||
std::set<TokenType> expectedTokens;
|
||||
@@ -47,6 +45,7 @@ private:
|
||||
void bump();
|
||||
|
||||
bool consume(TokenType tokenType);
|
||||
|
||||
bool check(TokenType tokenType);
|
||||
|
||||
void skipUntilNextKeyword();
|
||||
@@ -57,53 +56,79 @@ private:
|
||||
|
||||
template<typename T>
|
||||
PResult<std::vector<T>> parseList(std::optional<TokenType> openDelim,
|
||||
TokenType closeDelim,
|
||||
std::optional<TokenType> separator,
|
||||
bool allowTrailing,
|
||||
const std::function<PResult<T> ()> &parse_f);
|
||||
TokenType closeDelim,
|
||||
std::optional<TokenType> separator,
|
||||
bool allowTrailing,
|
||||
const std::function<PResult<T>()> &parse_f);
|
||||
|
||||
Spanner getSpanner();
|
||||
|
||||
// used to parse library and schema
|
||||
PResult<StringNode> parseString();
|
||||
|
||||
PResult<IdentifierNode> parseIdentifier();
|
||||
|
||||
PResult<NumberNode> parseNumber();
|
||||
|
||||
PResult<CountNode> parseCount();
|
||||
|
||||
PResult<PropertyNode> parseProperty(std::optional<TokenType> valueType);
|
||||
|
||||
PResult<EnumerationNode> parseEnumeration();
|
||||
|
||||
PResult<ValueNode> parseConnectionWire();
|
||||
|
||||
PResult<ComponentNode> parseComponent();
|
||||
|
||||
PResult<AddressSpaceNode> parseAddress();
|
||||
|
||||
PResult<PinNode> parsePin();
|
||||
|
||||
PResult<DisplayNode> parseDisplay();
|
||||
|
||||
PResult<PinConnectionNode> parsePinConnection();
|
||||
|
||||
PResult<AttributeNode> parseAttribute();
|
||||
|
||||
PResult<PopupNode> parsePopup();
|
||||
|
||||
PResult<RuleNode> parseRule();
|
||||
|
||||
PResult<BusNode> parseBus();
|
||||
|
||||
PResult<WireNode> parseWire();
|
||||
|
||||
PResult<ConnectionNode> parseConnection();
|
||||
|
||||
PResult<DisplayItemNode> parseDisplayItem();
|
||||
|
||||
PResult<IfStatementNode> parseIfStatement();
|
||||
|
||||
PResult<ValueNode> parseValue();
|
||||
|
||||
|
||||
// used to parse schema
|
||||
PResult<CountNode> parsePosition();
|
||||
PResult<InstanceNode> parseInstance();
|
||||
PResult<InstanceAttributeNode> parseInstanceAttribute();
|
||||
PResult<ConnectionInstanceNode> parseConnectionInstance();
|
||||
|
||||
public:
|
||||
ComdelParser(std::vector<Token> tokens);
|
||||
std::optional<SchemaNode> parseSchema();
|
||||
std::optional<LibraryNode> parse();
|
||||
const std::vector<SourceError>& getErrors();
|
||||
PResult<InstanceNode> parseInstance();
|
||||
|
||||
PResult<InstanceAttributeNode> parseInstanceAttribute();
|
||||
|
||||
PResult<ConnectionInstanceNode> parseConnectionInstance();
|
||||
|
||||
PResult<EnumNode<ComponentNode::ComponentType>> parseComponentType();
|
||||
|
||||
PResult<EnumNode<BusNode::BusType>> parseBusType();
|
||||
|
||||
PResult<EnumNode<PinConnectionNode::ConnectionType>> parseConnectionType();
|
||||
|
||||
public:
|
||||
explicit ComdelParser(std::vector<Token> tokens);
|
||||
|
||||
std::optional<SchemaNode> parseSchema();
|
||||
|
||||
std::optional<LibraryNode> parseLibrary();
|
||||
|
||||
const std::vector<SourceError> &getErrors();
|
||||
};
|
||||
|
||||
#endif // COMDEL_PARSER_H
|
||||
+76
-129
@@ -1,6 +1,6 @@
|
||||
#include "comdellexer.h"
|
||||
#include "token.h"
|
||||
#include "tokenstype.h"
|
||||
#include "tokens_type.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <cctype>
|
||||
@@ -36,14 +36,13 @@ inline bool isWhitespace(char ch) {
|
||||
*************************************************************************/
|
||||
|
||||
ComdelLexer::ComdelLexer(std::string fileName, std::string source,
|
||||
ParseContext* parseContext)
|
||||
: source(std::move(source)),
|
||||
parseContext(parseContext),
|
||||
// TODO Update this
|
||||
fileId(this->parseContext->addFile(fileName, this->source)),
|
||||
position(this->fileId, 1, 1, 0),
|
||||
ch(this->source[0])
|
||||
{}
|
||||
ParseContext *parseContext)
|
||||
: source(std::move(source)),
|
||||
parseContext(parseContext),
|
||||
// TODO Update this
|
||||
fileId(this->parseContext->addFile(fileName, this->source)),
|
||||
position(this->fileId, 1, 1, 0),
|
||||
ch(this->source[0]) {}
|
||||
|
||||
|
||||
LexerResult ComdelLexer::tokenize() {
|
||||
@@ -51,11 +50,11 @@ LexerResult ComdelLexer::tokenize() {
|
||||
tokenBegin = position;
|
||||
|
||||
auto tokenType = nextTokenType();
|
||||
if(!tokenType) {
|
||||
if (!tokenType) {
|
||||
errors.push_back(tokenType.error());
|
||||
continue;
|
||||
}
|
||||
if (tokenType == TokenType::WHITESPACE || tokenType == TokenType::COMMENT) {
|
||||
if (tokenType == TokenType::WHITESPACE || tokenType == TokenType::COMMENT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -67,9 +66,9 @@ LexerResult ComdelLexer::tokenize() {
|
||||
tokens.emplace_back(*tokenType, Span(tokenBegin, position), text);
|
||||
}
|
||||
|
||||
tokens.emplace_back( TokenType::END_OF_FILE, Span(position), "");
|
||||
tokens.emplace_back(TokenType::END_OF_FILE, Span(position), "");
|
||||
|
||||
return LexerResult { tokens, errors };
|
||||
return LexerResult{tokens, errors};
|
||||
}
|
||||
|
||||
|
||||
@@ -86,11 +85,11 @@ LexerResult ComdelLexer::tokenize() {
|
||||
unsigned ComdelLexer::takeNumberInRadix(Radix radix) {
|
||||
unsigned digitsTaken = 0;
|
||||
|
||||
while(true) {
|
||||
while (true) {
|
||||
if (digitIsValid(ch, radix)) { // skip and count real digits
|
||||
bump();
|
||||
digitsTaken++;
|
||||
} else if(ch == '_') { // skip underscores
|
||||
} else if (ch == '_') { // skip underscores
|
||||
bump();
|
||||
} else { // some other character => end of number
|
||||
return digitsTaken;
|
||||
@@ -103,26 +102,26 @@ bool ComdelLexer::digitIsValid(char ch, Radix radix) {
|
||||
|
||||
// Check valid digits
|
||||
// digit is 0..1
|
||||
if(ch == '1' || ch == '0') {
|
||||
if (ch == '1' || ch == '0') {
|
||||
// OK for all radixes
|
||||
return true;
|
||||
}
|
||||
//digit is 2..9
|
||||
if(isdigit(ch)) {
|
||||
if (isdigit(ch)) {
|
||||
// OK for decimal and hex radixes
|
||||
return(radix != Radix::BIN_NUMBER);
|
||||
return (radix != Radix::BIN_NUMBER);
|
||||
}
|
||||
// digit is a..f A..F
|
||||
else if(isxdigit(ch)) {
|
||||
// digit is a..f A..F
|
||||
else if (isxdigit(ch)) {
|
||||
// OK only for hex radix
|
||||
return(radix ==Radix::HEX_NUMBER);
|
||||
return (radix == Radix::HEX_NUMBER);
|
||||
}
|
||||
// NOT 0..9 a..f A..F
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
ComdelLexer::Radix ComdelLexer::takeRadix(){
|
||||
ComdelLexer::Radix ComdelLexer::takeRadix() {
|
||||
if (ch == '0') {
|
||||
char nextChar = peek();
|
||||
if (nextChar == 'x' || nextChar == 'X') {
|
||||
@@ -141,7 +140,7 @@ ComdelLexer::Radix ComdelLexer::takeRadix(){
|
||||
unsigned ComdelLexer::takeHexColor() {
|
||||
unsigned digitsTaken = 0;
|
||||
|
||||
while(true) {
|
||||
while (true) {
|
||||
if (digitIsValid(ch, Radix::HEX_NUMBER)) { // skip and count hex digits
|
||||
bump();
|
||||
digitsTaken++;
|
||||
@@ -162,10 +161,10 @@ PResult<TokenType> ComdelLexer::takeString() {
|
||||
// Check escape-sequences \t \n \\ \" but leave them in string.
|
||||
// They will be replaced in the constructor of StringLiteral AST-node.
|
||||
while (ch != '"' && ch != '\n' && !eof()) {
|
||||
if(ch == '"') {
|
||||
if (ch == '"') {
|
||||
// possible start of escape-sequence
|
||||
char nextCh = peek();
|
||||
if(nextCh == '\\' || nextCh == '\"' || nextCh == 't' || nextCh == 'n')
|
||||
if (nextCh == '\\' || nextCh == '\"' || nextCh == 't' || nextCh == 'n')
|
||||
bump(); // legal escape-sequence: skip backslash
|
||||
else
|
||||
return PError({Span(lo, position), "illegal escape-sequence (allowed: \\n \\\" \\\\ \\t"});
|
||||
@@ -177,12 +176,11 @@ PResult<TokenType> ComdelLexer::takeString() {
|
||||
return PError({Span(lo, position), "unterminated string"});
|
||||
}
|
||||
bump(); // skip closing "
|
||||
return TokenType::STRING;
|
||||
return TokenType::STRING;
|
||||
}
|
||||
|
||||
|
||||
PResult<TokenType> ComdelLexer::takeRawString()
|
||||
{
|
||||
PResult<TokenType> ComdelLexer::takeRawString() {
|
||||
Position lo = position;
|
||||
|
||||
if (ch != '`')
|
||||
@@ -198,7 +196,7 @@ PResult<TokenType> ComdelLexer::takeRawString()
|
||||
return PError({Span(lo, position), "unterminated string"});
|
||||
}
|
||||
bump(); // skip closing '
|
||||
return TokenType::STRING;
|
||||
return TokenType::STRING;
|
||||
}
|
||||
|
||||
|
||||
@@ -237,21 +235,16 @@ bool ComdelLexer::skipMultilineComment() {
|
||||
|
||||
|
||||
PResult<TokenType> ComdelLexer::nextTokenType() {
|
||||
if (isWhitespace(ch))
|
||||
{
|
||||
if (isWhitespace(ch)) {
|
||||
skipWhitespace();
|
||||
return TokenType::WHITESPACE;
|
||||
}
|
||||
else if (identifierStart(ch))
|
||||
{
|
||||
return TokenType::WHITESPACE;
|
||||
} else if (identifierStart(ch)) {
|
||||
bump();
|
||||
while (identifierContinue(ch))
|
||||
bump();
|
||||
return TokenType::IDENTIFIER;
|
||||
}
|
||||
else if (numberStart(ch))
|
||||
{
|
||||
if(ch == '-') {
|
||||
return TokenType::IDENTIFIER;
|
||||
} else if (numberStart(ch)) {
|
||||
if (ch == '-') {
|
||||
bump();
|
||||
}
|
||||
unsigned takenDigits;
|
||||
@@ -259,145 +252,99 @@ PResult<TokenType> ComdelLexer::nextTokenType() {
|
||||
takenDigits = takeNumberInRadix(radix);
|
||||
if (takenDigits == 0) {
|
||||
return PError({Span(tokenBegin, position),
|
||||
"no digits found for number, or misspelled number"});
|
||||
"no digits found for number, or misspelled number"});
|
||||
}
|
||||
if( isalnum(ch) ) {
|
||||
if (isalnum(ch)) {
|
||||
return PError({Span(tokenBegin, position),
|
||||
"illegal digit or letter found at the end of number"});
|
||||
"illegal digit or letter found at the end of number"});
|
||||
}
|
||||
return TokenType::NUMBER;
|
||||
}
|
||||
else if (ch == '!')
|
||||
{
|
||||
return TokenType::NUMBER;
|
||||
} else if (ch == '!') {
|
||||
bump();
|
||||
return TokenType::NOT;
|
||||
}
|
||||
|
||||
else if (ch == '<')
|
||||
{
|
||||
return TokenType::NOT;
|
||||
} else if (ch == '<') {
|
||||
bump();
|
||||
return TokenType::LT;
|
||||
}
|
||||
|
||||
else if (ch == '>')
|
||||
{
|
||||
return TokenType::LT;
|
||||
} else if (ch == '>') {
|
||||
bump();
|
||||
return TokenType::GT;
|
||||
}
|
||||
|
||||
else if (ch == '#')
|
||||
{
|
||||
return TokenType::GT;
|
||||
} else if (ch == '#') {
|
||||
bump();
|
||||
|
||||
if (digitIsValid(ch, Radix::HEX_NUMBER)) {
|
||||
unsigned takenDigits = takeHexColor();
|
||||
if (takenDigits != 6 && takenDigits != 8) {
|
||||
return PError({Span(tokenBegin, position),
|
||||
"hex-color must have 6 or 8 hex-digits"});
|
||||
"hex-color must have 6 or 8 hex-digits"});
|
||||
}
|
||||
if( isalnum(ch) ) {
|
||||
if (isalnum(ch)) {
|
||||
return PError({Span(tokenBegin, position),
|
||||
"illegal letter found at the end of hex-color"});
|
||||
"illegal letter found at the end of hex-color"});
|
||||
}
|
||||
return TokenType::COLOR;
|
||||
return TokenType::COLOR;
|
||||
} else {
|
||||
return PError({Span(tokenBegin, position),
|
||||
"unexpected #"});
|
||||
}
|
||||
}
|
||||
else if (ch == '@')
|
||||
{
|
||||
} else if (ch == '@') {
|
||||
bump();
|
||||
while (identifierContinue(ch))
|
||||
bump();
|
||||
return TokenType::KEYWORD;
|
||||
}
|
||||
else if (ch == '"')
|
||||
{
|
||||
return TokenType::KEYWORD;
|
||||
} else if (ch == '"') {
|
||||
return takeString();
|
||||
}
|
||||
else if (ch == '`')
|
||||
{
|
||||
} else if (ch == '`') {
|
||||
return takeRawString();
|
||||
}
|
||||
else if (ch == '(')
|
||||
{
|
||||
} else if (ch == '(') {
|
||||
bump();
|
||||
return TokenType::LPAREN;
|
||||
}
|
||||
else if (ch == ')')
|
||||
{
|
||||
return TokenType::LPAREN;
|
||||
} else if (ch == ')') {
|
||||
bump();
|
||||
return TokenType::RPAREN;
|
||||
}
|
||||
else if (ch == '[')
|
||||
{
|
||||
return TokenType::RPAREN;
|
||||
} else if (ch == '[') {
|
||||
bump();
|
||||
return TokenType::LBRACKET;
|
||||
}
|
||||
else if (ch == ']')
|
||||
{
|
||||
} else if (ch == ']') {
|
||||
bump();
|
||||
return TokenType::RBRACKET;
|
||||
}
|
||||
else if (ch == '{')
|
||||
{
|
||||
return TokenType::RBRACKET;
|
||||
} else if (ch == '{') {
|
||||
bump();
|
||||
return TokenType::LBRACE;
|
||||
}
|
||||
else if (ch == '}')
|
||||
{
|
||||
} else if (ch == '}') {
|
||||
bump();
|
||||
return TokenType::RBRACE;
|
||||
}
|
||||
else if (ch == '/')
|
||||
{
|
||||
} else if (ch == '/') {
|
||||
bump();
|
||||
if (ch == '/')
|
||||
{
|
||||
if (ch == '/') {
|
||||
bump();
|
||||
skipComment();
|
||||
return TokenType::COMMENT;
|
||||
} else if (ch == '*')
|
||||
{
|
||||
} else if (ch == '*') {
|
||||
bump();
|
||||
if (!skipMultilineComment())
|
||||
{
|
||||
if (!skipMultilineComment()) {
|
||||
return PError({Span(tokenBegin, position),
|
||||
"unterminated multiline comment"});
|
||||
"unterminated multiline comment"});
|
||||
}
|
||||
return TokenType::COMMENT;
|
||||
}
|
||||
return PError({Span(tokenBegin, position),
|
||||
"unexpected /"});
|
||||
}
|
||||
else if (ch == '.')
|
||||
{
|
||||
} else if (ch == '.') {
|
||||
bump();
|
||||
return TokenType::DOT;
|
||||
}
|
||||
else if (ch == ':')
|
||||
{
|
||||
} else if (ch == ':') {
|
||||
bump();
|
||||
return TokenType::COLON;
|
||||
}
|
||||
else if (ch == ';')
|
||||
{
|
||||
} else if (ch == ';') {
|
||||
bump();
|
||||
return TokenType::SEMICOLON;
|
||||
}
|
||||
else if (ch == ',')
|
||||
{
|
||||
} else if (ch == ',') {
|
||||
bump();
|
||||
return TokenType::COMMA;
|
||||
}
|
||||
else if (ch == '=')
|
||||
{
|
||||
} else if (ch == '=') {
|
||||
bump();
|
||||
return TokenType::EQUALS;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
std::stringstream message;
|
||||
message << "unexpected character `" << ch << "`";
|
||||
bump();
|
||||
@@ -409,11 +356,11 @@ PResult<TokenType> ComdelLexer::nextTokenType() {
|
||||
// Move position to the new character in input file.
|
||||
// Fetch the new character in 'ch'
|
||||
void ComdelLexer::bump(unsigned count) {
|
||||
for (unsigned i=0; i < count && !eof(); i++) {
|
||||
for (unsigned i = 0; i < count && !eof(); i++) {
|
||||
if (ch == '\n') {
|
||||
position.line += 1;
|
||||
position.col = 1;
|
||||
parseContext->getFile(fileId).addLineOffset(position.offset+1);
|
||||
parseContext->getFile(fileId).addLineOffset(position.offset + 1);
|
||||
} else {
|
||||
position.col += 1;
|
||||
}
|
||||
@@ -427,10 +374,10 @@ void ComdelLexer::bump(unsigned count) {
|
||||
// Fetch does not cross line boundary.
|
||||
// Returns \n when next char does not exist (end of line or end of file)
|
||||
char ComdelLexer::peek() {
|
||||
if(position.offset+1 == source.size()) // eof
|
||||
if (position.offset + 1 == source.size()) // eof
|
||||
return '\n';
|
||||
|
||||
return source[position.offset+1];
|
||||
return source[position.offset + 1];
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef COMDEL_LEXER_H
|
||||
#define COMDEL_LEXER_H
|
||||
|
||||
#include "parsecontext.h"
|
||||
#include "parse_context.h"
|
||||
#include "presult.h"
|
||||
#include "sourceerror.h"
|
||||
#include "source_error.h"
|
||||
#include "token.h"
|
||||
|
||||
|
||||
@@ -16,8 +16,7 @@ struct LexerResult {
|
||||
std::vector<SourceError> errors;
|
||||
};
|
||||
|
||||
class ComdelLexer
|
||||
{
|
||||
class ComdelLexer {
|
||||
|
||||
enum Radix {
|
||||
BIN_NUMBER = 2,
|
||||
@@ -28,19 +27,23 @@ class ComdelLexer
|
||||
std::string source;
|
||||
std::vector<Token> tokens;
|
||||
std::vector<SourceError> errors;
|
||||
ParseContext* parseContext;
|
||||
ParseContext *parseContext;
|
||||
unsigned fileId;
|
||||
|
||||
public:
|
||||
ComdelLexer(std::string fileName, std::string source, ParseContext* parseContext);
|
||||
ComdelLexer(std::string fileName, std::string source, ParseContext *parseContext);
|
||||
|
||||
LexerResult tokenize();
|
||||
|
||||
private:
|
||||
void skipWhitespace();
|
||||
|
||||
unsigned takeNumberInRadix(Radix radix);
|
||||
|
||||
unsigned takeHexColor();
|
||||
|
||||
bool digitIsValid(char ch, Radix radix);
|
||||
|
||||
Radix takeRadix();
|
||||
|
||||
PResult<TokenType> nextTokenType();
|
||||
@@ -50,13 +53,17 @@ private:
|
||||
char ch;
|
||||
|
||||
void skipComment();
|
||||
|
||||
bool skipMultilineComment();
|
||||
|
||||
PResult<TokenType> takeString();
|
||||
|
||||
PResult<TokenType> takeRawString();
|
||||
|
||||
void bump(unsigned count = 1);
|
||||
|
||||
char peek();
|
||||
|
||||
bool eof();
|
||||
};
|
||||
|
||||
|
||||
+1980
-1794
File diff suppressed because it is too large.
Load diff
@@ -1,4 +1,4 @@
|
||||
#include "parsecontext.h"
|
||||
#include "parse_context.h"
|
||||
#include "assert.h"
|
||||
|
||||
#include <iostream>
|
||||
@@ -6,31 +6,29 @@
|
||||
#include <cmath>
|
||||
|
||||
|
||||
ParseContext::ParseContext()
|
||||
{
|
||||
ParseContext::ParseContext() {
|
||||
applicationDir = std::string();
|
||||
}
|
||||
|
||||
unsigned ParseContext::addFile(const std::string& fileName,
|
||||
const std::string& source)
|
||||
{
|
||||
fileMap.push_back(SourceFile(fileName, source));
|
||||
unsigned ParseContext::addFile(const std::string &fileName,
|
||||
const std::string &source) {
|
||||
fileMap.emplace_back(fileName, source);
|
||||
return fileMap.size();
|
||||
}
|
||||
|
||||
SourceFile& ParseContext::getFile(unsigned fileId)
|
||||
{
|
||||
return fileMap[fileId-1];
|
||||
SourceFile &ParseContext::getFile(unsigned fileId) {
|
||||
return fileMap[fileId - 1];
|
||||
}
|
||||
|
||||
|
||||
struct pad {
|
||||
char ch; int count;
|
||||
char ch;
|
||||
int count;
|
||||
|
||||
pad(char ch, int count) : ch(ch), count(count) {}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, const pad& p) {
|
||||
std::ostream &operator<<(std::ostream &stream, const pad &p) {
|
||||
for (int i = 0; i < p.count; i++) {
|
||||
stream << p.ch;
|
||||
}
|
||||
@@ -40,16 +38,13 @@ std::ostream& operator<<(std::ostream& stream, const pad& p) {
|
||||
#define ATLAS_ASSERT(x) \
|
||||
do {} while(0)
|
||||
|
||||
void ParseContext::formatError(const SourceError& sourceError,
|
||||
std::ostream& stream,
|
||||
const std::string& ErrorOrWarning)
|
||||
{
|
||||
void ParseContext::formatError(const SourceError &sourceError,
|
||||
std::ostream &stream,
|
||||
const std::string &errorOrWarning) {
|
||||
ATLAS_ASSERT(sourceError.span.lo.col != 0
|
||||
&& sourceError.span.hi.col != 0);
|
||||
|
||||
SourceFile sourceFile = getFile(sourceError.span.lo.fileId);
|
||||
|
||||
stream << ErrorOrWarning << sourceError.message << std::endl;
|
||||
stream << errorOrWarning << sourceError.message << std::endl;
|
||||
|
||||
Span span = sourceError.span;
|
||||
|
||||
@@ -100,21 +95,17 @@ void ParseContext::formatError(const SourceError& sourceError,
|
||||
}
|
||||
|
||||
|
||||
|
||||
SourceFile::SourceFile(std::string fileName, std::string source)
|
||||
: fileName(std::move(fileName)), source(std::move(source))
|
||||
{
|
||||
: fileName(std::move(fileName)), source(std::move(source)) {
|
||||
lineOffsets.push_back(0);
|
||||
}
|
||||
|
||||
const std::string& SourceFile::getFileName() const
|
||||
{
|
||||
const std::string &SourceFile::getFileName() const {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
const std::string SourceFile::getLine(unsigned line) const
|
||||
{
|
||||
auto lineOffset = lineOffsets[line-1];
|
||||
std::string SourceFile::getLine(unsigned line) const {
|
||||
auto lineOffset = lineOffsets[line - 1];
|
||||
auto nextLF = source.find('\n', lineOffset);
|
||||
auto nextCR = source.find('\r', lineOffset);
|
||||
auto nl = std::min(nextCR, nextLF);
|
||||
@@ -122,7 +113,6 @@ const std::string SourceFile::getLine(unsigned line) const
|
||||
return source.substr(lineOffset, nl - lineOffset);
|
||||
}
|
||||
|
||||
void SourceFile::addLineOffset(unsigned offset)
|
||||
{
|
||||
void SourceFile::addLineOffset(unsigned offset) {
|
||||
lineOffsets.push_back(offset);
|
||||
}
|
||||
@@ -2,40 +2,39 @@
|
||||
#define PARSE_CONTEXT_H
|
||||
|
||||
|
||||
#include "sourceerror.h"
|
||||
#include "source_error.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
class SourceFile {
|
||||
std::string fileName;
|
||||
std::string source;
|
||||
std::vector<unsigned> lineOffsets;
|
||||
|
||||
public:
|
||||
// qqq source je CIJELI comdel fajl,
|
||||
// za inicijalizaciju source se koristi std::move, a možda treba biti referenca???
|
||||
SourceFile(std::string fileName, std::string source);
|
||||
|
||||
const std::string& getFileName() const;
|
||||
const std::string getLine(unsigned line) const;
|
||||
const std::string &getFileName() const;
|
||||
|
||||
std::string getLine(unsigned line) const;
|
||||
|
||||
void addLineOffset(unsigned offset);
|
||||
};
|
||||
|
||||
|
||||
class ParseContext
|
||||
{
|
||||
class ParseContext {
|
||||
std::string applicationDir;
|
||||
std::vector<SourceFile> fileMap;
|
||||
|
||||
public:
|
||||
ParseContext();
|
||||
|
||||
unsigned addFile(const std::string& fileName, const std::string& source);
|
||||
SourceFile& getFile(unsigned file);
|
||||
unsigned addFile(const std::string &fileName, const std::string &source);
|
||||
|
||||
void formatError(const SourceError &sourceError, std::ostream &stream, const std::string& ErrorOrWarning);
|
||||
SourceFile &getFile(unsigned file);
|
||||
|
||||
void formatError(const SourceError &sourceError, std::ostream &stream, const std::string &errorOrWarning);
|
||||
|
||||
};
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
#include "comdellexer.h"
|
||||
#include "comdelparser.h"
|
||||
#include "parserutil.h"
|
||||
#include "comdel_parser.h"
|
||||
#include "parser_util.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <QDir>
|
||||
|
||||
std::optional<LibraryNode> loadLibraryFromFile(ParseContext * parseContext,
|
||||
const char* name,
|
||||
std::ostream& stream)
|
||||
{
|
||||
std::optional<LibraryNode> load_library_from_file(ParseContext *parseContext,
|
||||
const char *name,
|
||||
std::ostream &stream) {
|
||||
std::ifstream in(name, std::ios::in | std::ios::binary);
|
||||
if( ! in ) {
|
||||
if (!in) {
|
||||
stream << "ERROR: cannot open file '" << name
|
||||
<< "' (file does not exist or is unreadable)" << std::endl;
|
||||
return std::nullopt;
|
||||
@@ -23,17 +22,17 @@ std::optional<LibraryNode> loadLibraryFromFile(ParseContext * parseContext,
|
||||
ComdelLexer lexer(name, source, parseContext);
|
||||
LexerResult lexerResult = lexer.tokenize();
|
||||
|
||||
if (lexerResult.errors.size()) {
|
||||
for (auto& error : lexerResult.errors) {
|
||||
if (!lexerResult.errors.empty()) {
|
||||
for (auto &error: lexerResult.errors) {
|
||||
parseContext->formatError(error, stream, "ERROR: ");
|
||||
}
|
||||
return std::nullopt; // if lexer has found errors => don't parse
|
||||
return std::nullopt; // if lexer has found errors => don't parseLibrary
|
||||
}
|
||||
|
||||
ComdelParser parser(lexerResult.tokens);
|
||||
auto unit = parser.parse();
|
||||
auto unit = parser.parseLibrary();
|
||||
if (!unit) {
|
||||
for (auto& error : parser.getErrors()) {
|
||||
for (auto &error: parser.getErrors()) {
|
||||
parseContext->formatError(error, stream, "ERROR: ");
|
||||
}
|
||||
return std::nullopt;
|
||||
@@ -43,12 +42,11 @@ std::optional<LibraryNode> loadLibraryFromFile(ParseContext * parseContext,
|
||||
}
|
||||
|
||||
|
||||
std::optional<SchemaNode> loadSchemaFromFile(ParseContext * parseContext,
|
||||
const char* name,
|
||||
std::ostream& stream)
|
||||
{
|
||||
std::optional<SchemaNode> load_schema_from_file(ParseContext *parseContext,
|
||||
const char *name,
|
||||
std::ostream &stream) {
|
||||
std::ifstream in(name, std::ios::in | std::ios::binary);
|
||||
if( ! in ) {
|
||||
if (!in) {
|
||||
stream << "ERROR: cannot open file '" << name
|
||||
<< "' (file does not exist or is unreadable)" << std::endl;
|
||||
return std::nullopt;
|
||||
@@ -59,32 +57,32 @@ std::optional<SchemaNode> loadSchemaFromFile(ParseContext * parseContext,
|
||||
ComdelLexer lexer(name, source, parseContext);
|
||||
LexerResult lexerResult = lexer.tokenize();
|
||||
|
||||
if (lexerResult.errors.size()) {
|
||||
for (auto& error : lexerResult.errors) {
|
||||
if (!lexerResult.errors.empty()) {
|
||||
for (auto &error: lexerResult.errors) {
|
||||
parseContext->formatError(error, stream, "ERROR: ");
|
||||
}
|
||||
return std::nullopt; // if lexer has found errors => don't parse
|
||||
return std::nullopt; // if lexer has found errors => don't parseLibrary
|
||||
}
|
||||
|
||||
ComdelParser parser(lexerResult.tokens);
|
||||
auto unit = parser.parseSchema();
|
||||
if (!unit) {
|
||||
for (auto& error : parser.getErrors()) {
|
||||
for (auto &error: parser.getErrors()) {
|
||||
parseContext->formatError(error, stream, "ERROR: ");
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if(unit->source) {
|
||||
if (unit->source) {
|
||||
QFileInfo info(name);
|
||||
auto filepath = info.absolutePath();
|
||||
QDir dir;
|
||||
dir.setCurrent(filepath);
|
||||
QDir::setCurrent(filepath);
|
||||
|
||||
QDir dir;
|
||||
auto libraryPath = dir.absoluteFilePath(QString::fromStdString(unit->source->asString()));
|
||||
|
||||
unit->library = loadLibraryFromFile(parseContext, libraryPath.toUtf8().data(), stream);
|
||||
if(unit->library == std::nullopt) {
|
||||
unit->library = load_library_from_file(parseContext, libraryPath.toUtf8().data(), stream);
|
||||
if (unit->library == std::nullopt) {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef PARSER_UTIL_H
|
||||
#define PARSER_UTIL_H
|
||||
|
||||
#include "ast_nodes.h"
|
||||
#include "parse_context.h"
|
||||
|
||||
std::optional<LibraryNode> load_library_from_file(ParseContext *parseContext,
|
||||
const char *name,
|
||||
std::ostream &stream);
|
||||
|
||||
std::optional<SchemaNode> load_schema_from_file(ParseContext *parseContext,
|
||||
const char *name,
|
||||
std::ostream &stream);
|
||||
|
||||
#endif // PARSER_UTIL_H
|
||||
@@ -1,15 +0,0 @@
|
||||
#ifndef PARSER_UTIL_H
|
||||
#define PARSER_UTIL_H
|
||||
|
||||
#include "astnode.h"
|
||||
#include "parsecontext.h"
|
||||
|
||||
std::optional<LibraryNode> loadLibraryFromFile(ParseContext * parseContext,
|
||||
const char* name,
|
||||
std::ostream& stream);
|
||||
|
||||
std::optional<SchemaNode> loadSchemaFromFile(ParseContext * parseContext,
|
||||
const char* name,
|
||||
std::ostream& stream);
|
||||
|
||||
#endif // PARSERUTIL_H
|
||||
+107
-151
@@ -30,142 +30,119 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
|
||||
namespace detail
|
||||
{
|
||||
namespace detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Implementation detail classes
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
struct default_copy
|
||||
{
|
||||
T* operator()(const T& t) const
|
||||
{
|
||||
template<class T>
|
||||
struct default_copy {
|
||||
T *operator()(const T &t) const {
|
||||
return new T(t);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct default_delete
|
||||
{
|
||||
void operator()(const T* t) const
|
||||
{
|
||||
template<class T>
|
||||
struct default_delete {
|
||||
void operator()(const T *t) const {
|
||||
delete t;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct control_block
|
||||
{
|
||||
template<class T>
|
||||
struct control_block {
|
||||
virtual ~control_block() = default;
|
||||
|
||||
virtual std::unique_ptr<control_block> clone() const = 0;
|
||||
|
||||
virtual T* ptr() = 0;
|
||||
virtual T *ptr() = 0;
|
||||
};
|
||||
|
||||
template <class T, class U = T>
|
||||
class direct_control_block : public control_block<T>
|
||||
{
|
||||
template<class T, class U = T>
|
||||
class direct_control_block : public control_block<T> {
|
||||
static_assert(!std::is_reference<U>::value, "");
|
||||
U u_;
|
||||
|
||||
public:
|
||||
template <class... Ts>
|
||||
explicit direct_control_block(Ts&&... ts) : u_(U(std::forward<Ts>(ts)...))
|
||||
{
|
||||
template<class... Ts>
|
||||
explicit direct_control_block(Ts &&... ts) : u_(U(std::forward<Ts>(ts)...)) {
|
||||
}
|
||||
|
||||
std::unique_ptr<control_block<T>> clone() const override
|
||||
{
|
||||
std::unique_ptr<control_block<T>> clone() const override {
|
||||
return std::make_unique<direct_control_block>(*this);
|
||||
}
|
||||
|
||||
T* ptr() override
|
||||
{
|
||||
T *ptr() override {
|
||||
return std::addressof(u_);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class U, class C = default_copy<U>,
|
||||
class D = default_delete<U>>
|
||||
class pointer_control_block : public control_block<T>, public C
|
||||
{
|
||||
template<class T, class U, class C = default_copy<U>,
|
||||
class D = default_delete<U>>
|
||||
class pointer_control_block : public control_block<T>, public C {
|
||||
std::unique_ptr<U, D> p_;
|
||||
|
||||
public:
|
||||
explicit pointer_control_block(U* u, C c = C{}, D d = D{})
|
||||
: C(std::move(c)), p_(u, std::move(d))
|
||||
{
|
||||
explicit pointer_control_block(U *u, C c = C{}, D d = D{})
|
||||
: C(std::move(c)), p_(u, std::move(d)) {
|
||||
}
|
||||
|
||||
explicit pointer_control_block(std::unique_ptr<U, D> p, C c = C{})
|
||||
: C(std::move(c)), p_(std::move(p))
|
||||
{
|
||||
: C(std::move(c)), p_(std::move(p)) {
|
||||
}
|
||||
|
||||
std::unique_ptr<control_block<T>> clone() const override
|
||||
{
|
||||
std::unique_ptr<control_block<T>> clone() const override {
|
||||
assert(p_);
|
||||
return std::make_unique<pointer_control_block>(
|
||||
C::operator()(*p_), static_cast<const C&>(*this), p_.get_deleter());
|
||||
C::operator()(*p_), static_cast<const C &>(*this), p_.get_deleter());
|
||||
}
|
||||
|
||||
T* ptr() override
|
||||
{
|
||||
T *ptr() override {
|
||||
return p_.get();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
class delegating_control_block : public control_block<T>
|
||||
{
|
||||
template<class T, class U>
|
||||
class delegating_control_block : public control_block<T> {
|
||||
std::unique_ptr<control_block<U>> delegate_;
|
||||
|
||||
public:
|
||||
explicit delegating_control_block(std::unique_ptr<control_block<U>> b)
|
||||
: delegate_(std::move(b))
|
||||
{
|
||||
: delegate_(std::move(b)) {
|
||||
}
|
||||
|
||||
std::unique_ptr<control_block<T>> clone() const override
|
||||
{
|
||||
std::unique_ptr<control_block<T>> clone() const override {
|
||||
return std::make_unique<delegating_control_block>(delegate_->clone());
|
||||
}
|
||||
|
||||
T* ptr() override
|
||||
{
|
||||
return static_cast<T*>(delegate_->ptr());
|
||||
T *ptr() override {
|
||||
return static_cast<T *>(delegate_->ptr());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // end namespace detail
|
||||
|
||||
class bad_poly_construction : std::exception
|
||||
{
|
||||
class bad_poly_construction : std::exception {
|
||||
public:
|
||||
bad_poly_construction() noexcept = default;
|
||||
|
||||
const char* what() const noexcept override
|
||||
{
|
||||
const char *what() const noexcept override {
|
||||
return "Dynamic and static type mismatch in poly "
|
||||
"construction";
|
||||
"construction";
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template<class T>
|
||||
class poly;
|
||||
|
||||
template <class T>
|
||||
struct is_poly : std::false_type
|
||||
{
|
||||
template<class T>
|
||||
struct is_poly : std::false_type {
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_poly<poly<T>> : std::true_type
|
||||
{
|
||||
template<class T>
|
||||
struct is_poly<poly<T>> : std::true_type {
|
||||
};
|
||||
|
||||
|
||||
@@ -173,23 +150,25 @@ struct is_poly<poly<T>> : std::true_type
|
||||
// `poly` class definition
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
class poly
|
||||
{
|
||||
template<class T>
|
||||
class poly {
|
||||
static_assert(!std::is_union<T>::value, "");
|
||||
static_assert(std::is_class<T>::value, "");
|
||||
|
||||
template <class U>
|
||||
friend class poly;
|
||||
template<class U>
|
||||
friend
|
||||
class poly;
|
||||
|
||||
template <class T_, class U, class... Ts>
|
||||
friend poly<T_> make_poly(Ts&&... ts);
|
||||
template <class T_, class... Ts>
|
||||
friend poly<T_> make_poly(Ts&&... ts);
|
||||
template <class T_, class U>
|
||||
template<class T_, class U, class... Ts>
|
||||
friend poly<T_> make_poly(Ts &&... ts);
|
||||
|
||||
template<class T_, class... Ts>
|
||||
friend poly<T_> make_poly(Ts &&... ts);
|
||||
|
||||
template<class T_, class U>
|
||||
friend poly<T_> poly_cast(poly<U> p);
|
||||
|
||||
T* ptr_ = nullptr;
|
||||
T *ptr_ = nullptr;
|
||||
std::unique_ptr<detail::control_block<T>> cb_;
|
||||
|
||||
public:
|
||||
@@ -204,17 +183,14 @@ public:
|
||||
// Constructors
|
||||
//
|
||||
|
||||
poly()
|
||||
{
|
||||
poly() {
|
||||
}
|
||||
|
||||
template <class U, class C = detail::default_copy<U>,
|
||||
class D = detail::default_delete<U>,
|
||||
class V = std::enable_if_t<std::is_convertible<U*, T*>::value>>
|
||||
explicit poly(U* u, C copier = C{}, D deleter = D{})
|
||||
{
|
||||
if (!u)
|
||||
{
|
||||
template<class U, class C = detail::default_copy<U>,
|
||||
class D = detail::default_delete<U>,
|
||||
class V = std::enable_if_t<std::is_convertible<U *, T *>::value>>
|
||||
explicit poly(U *u, C copier = C{}, D deleter = D{}) {
|
||||
if (!u) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -227,7 +203,7 @@ public:
|
||||
std::unique_ptr<U, D> p(u, std::move(deleter));
|
||||
|
||||
cb_ = std::make_unique<detail::pointer_control_block<T, U, C, D>>(
|
||||
std::move(p), std::move(copier));
|
||||
std::move(p), std::move(copier));
|
||||
ptr_ = u;
|
||||
}
|
||||
|
||||
@@ -236,10 +212,8 @@ public:
|
||||
// Copy-constructors
|
||||
//
|
||||
|
||||
poly(const poly& p)
|
||||
{
|
||||
if (!p)
|
||||
{
|
||||
poly(const poly &p) {
|
||||
if (!p) {
|
||||
return;
|
||||
}
|
||||
auto tmp_cb = p.cb_->clone();
|
||||
@@ -251,8 +225,7 @@ public:
|
||||
// Move-constructors
|
||||
//
|
||||
|
||||
poly(poly&& p) noexcept
|
||||
{
|
||||
poly(poly &&p) noexcept {
|
||||
ptr_ = p.ptr_;
|
||||
cb_ = std::move(p.cb_);
|
||||
p.ptr_ = nullptr;
|
||||
@@ -262,25 +235,23 @@ public:
|
||||
// Converting constructors
|
||||
//
|
||||
|
||||
template <class U,
|
||||
class V = std::enable_if_t<!std::is_same<T, U>::value &&
|
||||
std::is_convertible<U*, T*>::value>>
|
||||
poly(const poly<U>& p)
|
||||
{
|
||||
template<class U,
|
||||
class V = std::enable_if_t<!std::is_same<T, U>::value &&
|
||||
std::is_convertible<U *, T *>::value>>
|
||||
poly(const poly<U> &p) {
|
||||
poly<U> tmp(p);
|
||||
ptr_ = tmp.ptr_;
|
||||
cb_ = std::make_unique<detail::delegating_control_block<T, U>>(
|
||||
std::move(tmp.cb_));
|
||||
std::move(tmp.cb_));
|
||||
}
|
||||
|
||||
template <class U,
|
||||
class V = std::enable_if_t<!std::is_same<T, U>::value &&
|
||||
std::is_convertible<U*, T*>::value>>
|
||||
poly(poly<U>&& p)
|
||||
{
|
||||
template<class U,
|
||||
class V = std::enable_if_t<!std::is_same<T, U>::value &&
|
||||
std::is_convertible<U *, T *>::value>>
|
||||
poly(poly<U> &&p) {
|
||||
ptr_ = p.ptr_;
|
||||
cb_ = std::make_unique<detail::delegating_control_block<T, U>>(
|
||||
std::move(p.cb_));
|
||||
std::move(p.cb_));
|
||||
p.ptr_ = nullptr;
|
||||
}
|
||||
|
||||
@@ -288,14 +259,13 @@ public:
|
||||
// Forwarding constructor
|
||||
//
|
||||
|
||||
template <class U, class V = std::enable_if_t<
|
||||
std::is_convertible<std::decay_t<U>*, T*>::value &&
|
||||
!is_poly<std::decay_t<U>>::value>>
|
||||
poly(U&& u)
|
||||
: cb_(std::make_unique<
|
||||
detail::direct_control_block<T, std::decay_t<U>>>(
|
||||
std::forward<U>(u)))
|
||||
{
|
||||
template<class U, class V = std::enable_if_t<
|
||||
std::is_convertible<std::decay_t<U> *, T *>::value &&
|
||||
!is_poly<std::decay_t<U>>::value>>
|
||||
poly(U &&u)
|
||||
: cb_(std::make_unique<
|
||||
detail::direct_control_block<T, std::decay_t<U>>>(
|
||||
std::forward<U>(u))) {
|
||||
ptr_ = cb_->ptr();
|
||||
}
|
||||
|
||||
@@ -303,15 +273,12 @@ public:
|
||||
// Assignment
|
||||
//
|
||||
|
||||
poly& operator=(const poly& p)
|
||||
{
|
||||
if (std::addressof(p) == this)
|
||||
{
|
||||
poly &operator=(const poly &p) {
|
||||
if (std::addressof(p) == this) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (!p)
|
||||
{
|
||||
if (!p) {
|
||||
cb_.reset();
|
||||
ptr_ = nullptr;
|
||||
return *this;
|
||||
@@ -328,10 +295,8 @@ public:
|
||||
// Move-assignment
|
||||
//
|
||||
|
||||
poly& operator=(poly&& p) noexcept
|
||||
{
|
||||
if (std::addressof(p) == this)
|
||||
{
|
||||
poly &operator=(poly &&p) noexcept {
|
||||
if (std::addressof(p) == this) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -346,8 +311,7 @@ public:
|
||||
// Modifiers
|
||||
//
|
||||
|
||||
void swap(poly& p) noexcept
|
||||
{
|
||||
void swap(poly &p) noexcept {
|
||||
using std::swap;
|
||||
swap(ptr_, p.ptr_);
|
||||
swap(cb_, p.cb_);
|
||||
@@ -358,31 +322,26 @@ public:
|
||||
// Observers
|
||||
//
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
return (bool)cb_;
|
||||
explicit operator bool() const {
|
||||
return (bool) cb_;
|
||||
}
|
||||
|
||||
const T* operator->() const
|
||||
{
|
||||
const T *operator->() const {
|
||||
assert(ptr_);
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
const T& operator*() const
|
||||
{
|
||||
const T &operator*() const {
|
||||
assert(*this);
|
||||
return *ptr_;
|
||||
}
|
||||
|
||||
T* operator->()
|
||||
{
|
||||
T *operator->() {
|
||||
assert(*this);
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
T& operator*()
|
||||
{
|
||||
T &operator*() {
|
||||
assert(*this);
|
||||
return *ptr_;
|
||||
}
|
||||
@@ -391,18 +350,17 @@ public:
|
||||
//
|
||||
// poly creation
|
||||
//
|
||||
template <class T, class... Ts>
|
||||
poly<T> make_poly(Ts&&... ts)
|
||||
{
|
||||
template<class T, class... Ts>
|
||||
poly<T> make_poly(Ts &&... ts) {
|
||||
poly<T> p;
|
||||
p.cb_ = std::make_unique<detail::direct_control_block<T, T>>(
|
||||
std::forward<Ts>(ts)...);
|
||||
p.ptr_ = p.cb_->ptr();
|
||||
return std::move(p);
|
||||
}
|
||||
template <class T, class U, class... Ts>
|
||||
poly<T> make_poly(Ts&&... ts)
|
||||
{
|
||||
|
||||
template<class T, class U, class... Ts>
|
||||
poly<T> make_poly(Ts &&... ts) {
|
||||
poly<T> p;
|
||||
p.cb_ = std::make_unique<detail::direct_control_block<T, U>>(
|
||||
std::forward<Ts>(ts)...);
|
||||
@@ -410,32 +368,30 @@ poly<T> make_poly(Ts&&... ts)
|
||||
return std::move(p);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
const T* poly_view(const poly<U>& p) {
|
||||
template<class T, class U>
|
||||
const T *poly_view(const poly<U> &p) {
|
||||
if (p) {
|
||||
return dynamic_cast<const T*>(&*p);
|
||||
}
|
||||
else {
|
||||
return dynamic_cast<const T *>(&*p);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
T* poly_view(poly<U>& p) {
|
||||
template<class T, class U>
|
||||
T *poly_view(poly<U> &p) {
|
||||
if (p) {
|
||||
return dynamic_cast<T*>(&*p);
|
||||
}
|
||||
else {
|
||||
return dynamic_cast<T *>(&*p);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
template<class T, class U>
|
||||
poly<T> poly_cast(poly<U> p) {
|
||||
poly<T> ret;
|
||||
if (T* ptr = dynamic_cast<T*>(&*p)) {
|
||||
if (T *ptr = dynamic_cast<T *>(&*p)) {
|
||||
ret.cb_ = std::make_unique<detail::delegating_control_block<T, U>>(
|
||||
std::move(p.cb_));
|
||||
std::move(p.cb_));
|
||||
ret.ptr_ = ret.cb_->ptr();
|
||||
}
|
||||
return ret;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define PRESULT_H
|
||||
|
||||
#include "expected.h"
|
||||
#include "sourceerror.h"
|
||||
#include "source_error.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
@@ -32,19 +32,18 @@ using PError = tl::unexpected<SourceError>;
|
||||
|
||||
/// Holds either an AST node or an error
|
||||
/// The value MUST be checked before usage, e.g. using RETURN_IF_ERR
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
struct PResult : tl::expected<T, SourceError> {
|
||||
using tl::expected<T, SourceError>::expected;
|
||||
|
||||
/// Implicit conversion from PResult<U> to PResult<T>
|
||||
/// if U is convertible to T
|
||||
template <typename U, class V = std::enable_if_t<std::is_convertible<std::decay_t<U>, T>::value>>
|
||||
template<typename U, class V = std::enable_if_t<std::is_convertible<std::decay_t<U>, T>::value>>
|
||||
PResult(PResult<U> presult) :
|
||||
tl::expected<T, SourceError>(presult ? PResult<T>(*presult) : PError(presult.error()))
|
||||
{}
|
||||
tl::expected<T, SourceError>(presult ? PResult<T>(*presult) : PError(presult.error())) {}
|
||||
};
|
||||
|
||||
/// Alternative to PResult that is returned from parse* functions
|
||||
/// Alternative to PResult that is returned from parseLibrary* functions
|
||||
/// that only consume one token so they can fail without affecting
|
||||
/// the parser state
|
||||
template<typename T>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#include "source_error.h"
|
||||
|
||||
|
||||
SourceError::SourceError(Span span, std::string message)
|
||||
: span(span), message(std::move(message)) {}
|
||||
File renamed without changes.
@@ -1,6 +0,0 @@
|
||||
#include "sourceerror.h"
|
||||
|
||||
|
||||
SourceError::SourceError(Span span, std::string message)
|
||||
: span(std::move(span)), message(std::move(message))
|
||||
{}
|
||||
+8
-17
@@ -4,32 +4,23 @@
|
||||
|
||||
|
||||
Position::Position()
|
||||
: fileId(0), line(0), col(0), offset(0)
|
||||
{}
|
||||
: fileId(0), line(0), col(0), offset(0) {}
|
||||
|
||||
Position::Position(unsigned file, unsigned line, unsigned col, unsigned offset)
|
||||
: fileId(file), line(line), col(col), offset(offset)
|
||||
{}
|
||||
: fileId(file), line(line), col(col), offset(offset) {}
|
||||
|
||||
Span::Span()
|
||||
: lo(0, 0, 0, 0), hi(0, 0, 0, 0)
|
||||
{}
|
||||
: lo(0, 0, 0, 0), hi(0, 0, 0, 0) {}
|
||||
|
||||
Span::Span(Position begin, Position end)
|
||||
: lo(begin), hi(end)
|
||||
{}
|
||||
: lo(begin), hi(end) {}
|
||||
|
||||
Span::Span(Position begin)
|
||||
: Span(begin, Position(begin.fileId, begin.line, begin.col+1, begin.offset+1))
|
||||
{}
|
||||
: Span(begin, Position(begin.fileId, begin.line, begin.col + 1, begin.offset + 1)) {}
|
||||
|
||||
Span Span::to(const Span &span) const
|
||||
{
|
||||
return Span(this->lo, span.hi);
|
||||
Span Span::to(const Span &span) const {
|
||||
return {this->lo, span.hi};
|
||||
}
|
||||
|
||||
Token::Token(TokenType type, Span span, std::string text)
|
||||
: type(type)
|
||||
, span(std::move(span))
|
||||
, text(std::move(text))
|
||||
{}
|
||||
: type(type), span(span), text(std::move(text)) {}
|
||||
@@ -12,6 +12,7 @@ struct Position {
|
||||
unsigned offset;
|
||||
|
||||
Position();
|
||||
|
||||
Position(unsigned fileId, unsigned line, unsigned col, unsigned offset);
|
||||
};
|
||||
|
||||
@@ -23,10 +24,12 @@ struct Span {
|
||||
Position hi;
|
||||
|
||||
Span();
|
||||
|
||||
Span(Position lo, Position hi);
|
||||
|
||||
Span(Position lo);
|
||||
|
||||
Span to(const Span& span) const;
|
||||
Span to(const Span &span) const;
|
||||
};
|
||||
|
||||
enum class TokenType {
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
#include "tokens_type.h"
|
||||
|
||||
enum TokenClass {
|
||||
KEYWORD_NAME = 4,
|
||||
TOKENIZABLE = 8
|
||||
};
|
||||
|
||||
|
||||
struct TokenInfo {
|
||||
std::string text;
|
||||
unsigned short attributes;
|
||||
};
|
||||
|
||||
|
||||
struct TokenTables {
|
||||
std::unordered_map<TokenType, TokenInfo> allTokensInfo;
|
||||
std::unordered_map<std::string, TokenType> keywords;
|
||||
|
||||
TokenType tokenize(std::string value, TokenType initial);
|
||||
|
||||
bool is_keyword(TokenType token);
|
||||
|
||||
void add(TokenType tokenType, const std::string &txt,
|
||||
unsigned short attribs = 0);
|
||||
|
||||
TokenTables();
|
||||
};
|
||||
|
||||
|
||||
static TokenTables tokenTables;
|
||||
|
||||
void TokenTables::add(TokenType tokenType, const std::string &txt,
|
||||
unsigned short attribs) {
|
||||
allTokensInfo[tokenType] = TokenInfo{txt, attribs};
|
||||
if (attribs & KEYWORD_NAME)
|
||||
keywords[txt] = tokenType;
|
||||
}
|
||||
|
||||
TokenTables::TokenTables() {
|
||||
|
||||
add(TokenType::IDENTIFIER, "identifier");
|
||||
add(TokenType::KEYWORD, "keyword", KEYWORD_NAME);
|
||||
|
||||
// Literals (bool is not here, it has two keywords: false and true)
|
||||
add(TokenType::NUMBER, "number");
|
||||
add(TokenType::STRING, "string");
|
||||
add(TokenType::COLOR, "color");
|
||||
|
||||
// Parentheses of all kinds
|
||||
add(TokenType::LPAREN, "(");
|
||||
add(TokenType::RPAREN, ")");
|
||||
add(TokenType::LBRACKET, "[");
|
||||
add(TokenType::RBRACKET, "]");
|
||||
add(TokenType::LBRACE, "{");
|
||||
add(TokenType::RBRACE, "}");
|
||||
add(TokenType::LT, "<");
|
||||
add(TokenType::GT, ">");
|
||||
|
||||
// assignments
|
||||
add(TokenType::EQUALS, "=");
|
||||
|
||||
// miscellaneous
|
||||
add(TokenType::DOT, ".");
|
||||
add(TokenType::COLON, ":");
|
||||
add(TokenType::SEMICOLON, ";");
|
||||
add(TokenType::COMMA, ",");
|
||||
add(TokenType::WHITESPACE, "whitespace");
|
||||
add(TokenType::COMMENT, "comment");
|
||||
|
||||
add(TokenType::TRUE, "true", TOKENIZABLE);
|
||||
add(TokenType::FALSE, "false", TOKENIZABLE);
|
||||
|
||||
add(TokenType::IF, "if", TOKENIZABLE);
|
||||
add(TokenType::ELSE, "else", TOKENIZABLE);
|
||||
|
||||
add(TokenType::DEFAULT, "default", TOKENIZABLE);
|
||||
add(TokenType::NIL, "null", TOKENIZABLE);
|
||||
|
||||
// all keywords
|
||||
add(TokenType::KW_NAME, "@name", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_INFO, "@info", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_HEADER, "@header", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_COMPONENT_HEADER, "@componentHeader", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_DIRECTORY, "@directory", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_LIBRARY, "@library", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_ADDRESS, "@address", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_COMPONENT, "@component", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_MESSAGES, "@messages", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_INSTANCE_NAME, "@instanceName", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_COUNT, "@count", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_DISPLAY, "@display", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_PIN, "@pin", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_TOOLTIP, "@tooltip", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_CONNECTION, "@connection", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_ATTRIBUTE, "@attribute", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_SOURCE, "@source", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_POPUP, "@popup", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_RULE, "@rule", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_TITLE, "@title", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_TEXT, "@text", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_BUS, "@bus", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_WIRES, "@wires", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_ENUMERATED, "@enumerated", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_WIRE, "@wire", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_INSTANCE, "@instance", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_SCHEMA, "@schema", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_POSITION, "@position", TOKENIZABLE | KEYWORD_NAME);
|
||||
add(TokenType::KW_SIZE, "@size", TOKENIZABLE | KEYWORD_NAME);
|
||||
|
||||
// All types
|
||||
add(TokenType::INT_TYPE, "int", TOKENIZABLE);
|
||||
add(TokenType::STRING_TYPE, "string", TOKENIZABLE);
|
||||
add(TokenType::BOOL_TYPE, "bool", TOKENIZABLE);
|
||||
add(TokenType::WIRE_TYPE, "wire", TOKENIZABLE);
|
||||
|
||||
// WireNode types
|
||||
add(TokenType::WIRE_DEFAULT, "normal_wire", TOKENIZABLE);
|
||||
add(TokenType::WIRE_AND, "wired_and", TOKENIZABLE);
|
||||
add(TokenType::WIRE_OR, "wired_or", TOKENIZABLE);
|
||||
add(TokenType::R_WIRE, "r_wire", TOKENIZABLE);
|
||||
|
||||
// ComponentNode types
|
||||
add(TokenType::CT_MEMORY, "memory", TOKENIZABLE);
|
||||
add(TokenType::CT_PROCESSOR, "processor", TOKENIZABLE);
|
||||
|
||||
// PinNode type
|
||||
add(TokenType::PIN_IN, "in", TOKENIZABLE);
|
||||
add(TokenType::PIN_OUT, "out", TOKENIZABLE);
|
||||
add(TokenType::PIN_IN_OUT, "inOut", TOKENIZABLE);
|
||||
|
||||
// ActionNode types
|
||||
add(TokenType::ERROR, "error", TOKENIZABLE);
|
||||
add(TokenType::WARNING, "warning", TOKENIZABLE);
|
||||
|
||||
|
||||
// WireNode settings types
|
||||
add(TokenType::HIDDEN, "hidden", TOKENIZABLE);
|
||||
add(TokenType::TERMINATE_WITH, "terminate_with", TOKENIZABLE);
|
||||
|
||||
// Miscelaneous
|
||||
add(TokenType::END_OF_FILE, "eof");
|
||||
}
|
||||
|
||||
|
||||
const std::string &tokenTypeToString(TokenType tokenType) {
|
||||
return tokenTables.allTokensInfo[tokenType].text;
|
||||
}
|
||||
|
||||
TokenType TokenTables::tokenize(std::string value, TokenType initial) {
|
||||
for (auto &[key, param]: allTokensInfo) {
|
||||
if (param.attributes & TOKENIZABLE && param.text == value) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
return initial;
|
||||
}
|
||||
|
||||
bool TokenTables::is_keyword(TokenType token) {
|
||||
for (auto &[key, param]: allTokensInfo) {
|
||||
if (param.attributes & KEYWORD_NAME && key == token) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
TokenType from_token(std::string value, TokenType initial) {
|
||||
return tokenTables.tokenize(value, initial);
|
||||
}
|
||||
|
||||
bool is_keyword(TokenType tokenType) {
|
||||
return tokenTables.is_keyword(tokenType);
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
||||
const std::string& tokenTypeToString(TokenType tokenType);
|
||||
const std::string &tokenTypeToString(TokenType tokenType);
|
||||
|
||||
TokenType from_token(std::string value, TokenType initial);
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
#include "tokenstype.h"
|
||||
|
||||
enum TokenClass {
|
||||
BUILT_IN_FUNC = 1,
|
||||
DATA_TYPE = 2,
|
||||
KEYWORD_NAME = 4,
|
||||
TOKENIZABLE = 8
|
||||
};
|
||||
|
||||
|
||||
struct TokenInfo {
|
||||
std::string text;
|
||||
unsigned short attributes;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct TokenTables {
|
||||
std::unordered_map<TokenType, TokenInfo> allTokensInfo;
|
||||
std::unordered_map<std::string, TokenType> keywords;
|
||||
|
||||
TokenType tokenize(std::string value, TokenType initial);
|
||||
bool is_keyword(TokenType token);
|
||||
|
||||
void add(TokenType tokenType, const std::string& txt,
|
||||
unsigned short attribs = 0);
|
||||
|
||||
TokenTables();
|
||||
};
|
||||
|
||||
|
||||
static TokenTables tokenTables;
|
||||
|
||||
void TokenTables::add (TokenType tokenType, const std::string& txt,
|
||||
unsigned short attribs)
|
||||
{
|
||||
allTokensInfo[tokenType] = TokenInfo{txt, attribs};
|
||||
if(attribs & KEYWORD_NAME)
|
||||
keywords[txt] = tokenType;
|
||||
}
|
||||
|
||||
TokenTables::TokenTables() {
|
||||
|
||||
add( TokenType::IDENTIFIER, "identifier" );
|
||||
add( TokenType::KEYWORD, "keyword" , KEYWORD_NAME);
|
||||
|
||||
// Literals (bool is not here, it has two keywords: false and true)
|
||||
add( TokenType::NUMBER, "number");
|
||||
add( TokenType::STRING, "string");
|
||||
add( TokenType::COLOR, "color");
|
||||
|
||||
// Parentheses of all kinds
|
||||
add( TokenType::LPAREN, "(" );
|
||||
add( TokenType::RPAREN, ")" );
|
||||
add( TokenType::LBRACKET, "[" );
|
||||
add( TokenType::RBRACKET, "]" );
|
||||
add( TokenType::LBRACE, "{" );
|
||||
add( TokenType::RBRACE, "}" );
|
||||
add( TokenType::LT, "<" );
|
||||
add( TokenType::GT, ">" );
|
||||
|
||||
// assignments
|
||||
add( TokenType::EQUALS, "=" );
|
||||
|
||||
// miscellaneous
|
||||
add( TokenType::DOT, "." );
|
||||
add( TokenType::COLON, ":" );
|
||||
add( TokenType::SEMICOLON, ";" );
|
||||
add( TokenType::COMMA, "," );
|
||||
add( TokenType::WHITESPACE, "whitespace" );
|
||||
add( TokenType::COMMENT, "comment" );
|
||||
|
||||
add( TokenType::TRUE, "true", TOKENIZABLE ),
|
||||
add( TokenType::FALSE, "false", TOKENIZABLE),
|
||||
|
||||
add( TokenType::IF, "if", TOKENIZABLE ),
|
||||
add( TokenType::ELSE, "else", TOKENIZABLE),
|
||||
|
||||
add( TokenType::DEFAULT, "default", TOKENIZABLE),
|
||||
add( TokenType::NIL, "null", TOKENIZABLE),
|
||||
|
||||
// all keywords
|
||||
add( TokenType::KW_NAME, "@name", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_INFO, "@info", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_HEADER, "@header", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_COMPONENT_HEADER, "@componentHeader", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_DIRECTORY, "@directory", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_LIBRARY, "@library", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_ADDRESS, "@address", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_COMPONENT, "@component", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_MESSAGES, "@messages", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_INSTANCE_NAME, "@instanceName", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_COUNT, "@count", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_DISPLAY, "@display", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_PIN, "@pin", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_TOOLTIP, "@tooltip", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_CONNECTION, "@connection", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_ATTRIBUTE, "@attribute", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_SOURCE, "@source", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_POPUP, "@popup", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_RULE, "@rule", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_TITLE, "@title", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_TEXT, "@text", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_BUS, "@bus", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_WIRES, "@wires", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_ENUMERATED, "@enumerated", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_WIRE, "@wire", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_INSTANCE, "@instance", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_SCHEMA, "@schema", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_POSITION, "@position", TOKENIZABLE | KEYWORD_NAME),
|
||||
add( TokenType::KW_SIZE, "@size", TOKENIZABLE | KEYWORD_NAME),
|
||||
|
||||
// All types
|
||||
add( TokenType::INT_TYPE, "int", TOKENIZABLE),
|
||||
add( TokenType::STRING_TYPE, "string", TOKENIZABLE),
|
||||
add( TokenType::BOOL_TYPE, "bool", TOKENIZABLE),
|
||||
add( TokenType::WIRE_TYPE, "wire", TOKENIZABLE),
|
||||
|
||||
// WireNode types
|
||||
add( TokenType::WIRE_DEFAULT, "normal_wire", TOKENIZABLE),
|
||||
add( TokenType::WIRE_AND, "wired_and", TOKENIZABLE),
|
||||
add( TokenType::WIRE_OR, "wired_or", TOKENIZABLE),
|
||||
add( TokenType::R_WIRE, "r_wire", TOKENIZABLE),
|
||||
|
||||
// ComponentNode types
|
||||
add( TokenType::CT_MEMORY, "memory", TOKENIZABLE),
|
||||
add( TokenType::CT_PROCESSOR, "processor", TOKENIZABLE),
|
||||
|
||||
// PinNode type
|
||||
add( TokenType::PIN_IN, "in", TOKENIZABLE),
|
||||
add( TokenType::PIN_OUT, "out", TOKENIZABLE),
|
||||
add( TokenType::PIN_IN_OUT, "inOut", TOKENIZABLE),
|
||||
|
||||
// ActionNode types
|
||||
add( TokenType::ERROR, "error", TOKENIZABLE),
|
||||
add( TokenType::WARNING, "warning", TOKENIZABLE),
|
||||
|
||||
|
||||
// WireNode settings types
|
||||
add( TokenType::HIDDEN, "hidden", TOKENIZABLE),
|
||||
add( TokenType::TERMINATE_WITH, "terminate_with", TOKENIZABLE),
|
||||
|
||||
// Miscelaneous
|
||||
add( TokenType::END_OF_FILE, "eof" );
|
||||
}
|
||||
|
||||
|
||||
const std::string &tokenTypeToString(TokenType tokenType) {
|
||||
return tokenTables.allTokensInfo[tokenType].text;
|
||||
}
|
||||
|
||||
TokenType TokenTables::tokenize(std::string value, TokenType initial) {
|
||||
for(auto& [key, param]: allTokensInfo) {
|
||||
if(param.attributes & TOKENIZABLE && param.text == value) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
return initial;
|
||||
}
|
||||
|
||||
bool TokenTables::is_keyword(TokenType token) {
|
||||
for(auto& [key, param]: allTokensInfo) {
|
||||
if(param.attributes & KEYWORD_NAME && key == token) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
TokenType from_token(std::string value, TokenType initial) {
|
||||
return tokenTables.tokenize(value, initial);
|
||||
}
|
||||
|
||||
bool is_keyword(TokenType tokenType) {
|
||||
return tokenTables.is_keyword(tokenType);
|
||||
}
|
||||
Reference in new issue
Block a user