Basic refactor

This commit is contained in:
Borna Rajković committed 2022-05-27 08:18:17 +02:00
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
View File
@@ -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];
}
+13 -6
View File
@@ -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
View File
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;
}
}
+15
View File
@@ -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
-15
View File
@@ -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
View File
@@ -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;
+5 -6
View File
@@ -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>
+5
View File
@@ -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.
-6
View File
@@ -1,6 +0,0 @@
#include "sourceerror.h"
SourceError::SourceError(Span span, std::string message)
: span(std::move(span)), message(std::move(message))
{}
+8 -17
View File
@@ -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)) {}
+4 -1
View File
@@ -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 {
+173
View File
@@ -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);
-176
View File
@@ -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);
}