Add parser
diff --git a/.gitignore b/.gitignore
index 1c85d0e..82ffdc1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
.idea
cmake-build-*
+*.user
+build
diff --git a/AstNode.cpp b/AstNode.cpp
new file mode 100644
index 0000000..7bb84fa
--- /dev/null
+++ b/AstNode.cpp
@@ -0,0 +1,35 @@
+#include "AstNode.h"
+
+AstNode::AstNode(QString function, QList<AstNode> args)
+{
+ _type = FUNC;
+ _stringVal = function;
+ _listVal = args;
+}
+
+QList<AstNode> AstNode::funcArgs()
+{
+ return _listVal;
+}
+
+bool AstNode::isFunc() const
+{
+ return _type == FUNC;
+}
+
+AstNode::operator QString() const
+{
+ if (isFunc())
+ {
+ QStringList args;
+
+ for (const AstNode &node : _listVal)
+ {
+ args.append(static_cast<QString>(node));
+ }
+
+ return "<" + _stringVal + " " + args.join(" ") + ">";
+ }
+
+ return TokenBase<AstNode>::operator QString();
+}
diff --git a/AstNode.h b/AstNode.h
new file mode 100644
index 0000000..b10872a
--- /dev/null
+++ b/AstNode.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "Token.h"
+
+class AstNode : public TokenBase<AstNode>
+{
+public:
+ using TokenBase::TokenBase;
+
+ explicit AstNode(QString function, QList<AstNode> args);
+
+ enum
+ {
+ FUNC = TOKEN_TYPE_LAST
+ };
+
+ QList<AstNode> funcArgs();
+
+ bool isFunc() const;
+
+ operator QString() const;
+};
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 61c401e..472fecc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,9 +11,9 @@
Core
REQUIRED)
-add_executable(REFAL main.cpp Token.cpp Token.h Matcher.cpp Matcher.h VarContext.cpp VarContext.h)
+add_executable(REFAL main.cpp Token.cpp Token.h Matcher.cpp Matcher.h VarContext.cpp VarContext.h Parser.cpp Parser.h AstNode.cpp AstNode.h)
target_link_libraries(REFAL
Qt::Core
)
-add_compile_options("-fsanitize=address")
\ No newline at end of file
+add_compile_options("-fsanitize=address")
diff --git a/Matcher.cpp b/Matcher.cpp
index 3fc4670..427bd76 100644
--- a/Matcher.cpp
+++ b/Matcher.cpp
@@ -2,8 +2,10 @@
#include <QDebug>
-MatchResult match(QList<Token> data, QList<Token> pattern, VarContext context) {
- if (data.empty() && pattern.empty()) {
+MatchResult match(QList<Token> data, QList<Token> pattern, VarContext context)
+{
+ if (data.empty() && pattern.empty())
+ {
return MatchResult{true, context};
}
@@ -11,92 +13,112 @@
Token dataHead = data.first();
pattern.removeFirst();
- if (ph.isSym() || ph.isIdent()) {
- if (ph == data.first()) {
+ if (ph.isSym() || ph.isIdent())
+ {
+ if (ph == data.first())
+ {
data.removeFirst();
return match(data, pattern, context);
- } else {
+ }
+ else
+ {
return MatchResult{false, context};
}
- } else if (ph.isParen()) {
+ }
+ else if (ph.isParen())
+ {
data.removeFirst();
- qDebug() << "parens, dh = " << dataHead;
- qDebug() << "Matching parens" << dataHead.parenContent() << ph.parenContent();
-
auto result = match(dataHead.parenContent(), ph.parenContent(), context);
- qDebug() << "parens result was" << result.success << "in ctx" << result.context;
-
- if (result.success) {
+ if (result.success)
+ {
return match(data, pattern, result.context);
- } else {
+ }
+ else
+ {
return MatchResult{false, result.context};
}
- } else if (ph.isVar()) {
+ }
+ else if (ph.isVar())
+ {
// is var bound?
- if (context.exists(ph.name())) {
+ if (context.exists(ph.name()))
+ {
// TODO: handle error elegantly if types don't match up (let's just assume the user isn't stupid)
- switch (ph.varType()) {
- case 's':
- case 't':
- if (context.singleVar(ph.name()) == dataHead) {
- data.removeFirst();
- return match(data, pattern, context);
- } else {
- return MatchResult{false, context};
- }
- case 'e':
- QList<Token> expected = context.expressionVar(ph.name());
+ switch (ph.varType())
+ {
+ case 's':
+ case 't':
+ if (context.singleVar(ph.name()) == dataHead)
+ {
+ data.removeFirst();
+ return match(data, pattern, context);
+ }
+ else
+ {
+ return MatchResult{false, context};
+ }
+ case 'e':
+ QList<Token> expected = context.expressionVar(ph.name());
- if (listStartsWith(data, expected)) {
- listDrop(data, expected.length());
- return match(data, pattern, context);
- } else {
- return MatchResult{false, context};
- }
+ if (listStartsWith(data, expected))
+ {
+ listDrop(data, expected.length());
+ return match(data, pattern, context);
+ }
+ else
+ {
+ return MatchResult{false, context};
+ }
}
- } else {
+ }
+ else
+ {
bool typeIsOk = false;
- switch (ph.varType()) {
- case 't':
- if (dataHead.isParen())
- typeIsOk = true;
+ switch (ph.varType())
+ {
+ case 't':
+ if (dataHead.isParen())
+ typeIsOk = true;
- case 's':
- if (dataHead.isSym() || dataHead.isIdent())
- typeIsOk = true;
+ case 's':
+ if (dataHead.isSym() || dataHead.isIdent())
+ typeIsOk = true;
- if (!typeIsOk) {
- return MatchResult{false, context};
- }
-
- context.add(ph.varType(), ph.name(), dataHead);
- data.removeFirst();
-
- return match(data, pattern, context);
-
- case 'e':
- // Now this is tricky
- for (int matchSyms = 1; matchSyms < data.length(); matchSyms++) {
- QList<Token> slice = listSlice(data, 0, matchSyms);
- VarContext newContext = context;
- newContext.add(ph.varType(), ph.name(), slice);
-
- MatchResult tryMatch = match(listSlice(data, matchSyms, data.length()), pattern, newContext);
- if (tryMatch.success) {
- return tryMatch;
- }
- // else matchSyms ++
- }
- // If this worked we would have returned already
+ if (!typeIsOk)
+ {
return MatchResult{false, context};
+ }
- default:
- qDebug() << "#TYPE_ERROR";
- return MatchResult{false, context};
+ context.add(ph.varType(), ph.name(), dataHead);
+ data.removeFirst();
+
+ return match(data, pattern, context);
+
+ case 'e':
+ // Now this is tricky
+ for (int matchSyms = 1; matchSyms < data.length(); matchSyms++)
+ {
+ QList<Token> slice = listSlice(data, 0, matchSyms);
+ VarContext newContext = context;
+ newContext.add(ph.varType(), ph.name(), slice);
+
+ MatchResult tryMatch = match(listSlice(data, matchSyms, data.length()), pattern, newContext);
+ if (tryMatch.success)
+ {
+ return tryMatch;
+ }
+ // else matchSyms ++
+ }
+ // If this worked we would have returned already
+ return MatchResult{false, context};
+
+ default:
+ qDebug() << "#TYPE_ERROR";
+ return MatchResult{false, context};
}
}
}
diff --git a/Matcher.h b/Matcher.h
index 84aee15..24fc795 100644
--- a/Matcher.h
+++ b/Matcher.h
@@ -3,17 +3,20 @@
#include "Token.h"
#include "VarContext.h"
-struct MatchResult {
+struct MatchResult
+{
bool success;
VarContext context;
};
template <typename T>
-bool listStartsWith(const QList<T> &haystack, const QList<T> &needle) {
+bool listStartsWith(const QList<T> &haystack, const QList<T> &needle)
+{
if (needle.length() > haystack.length())
return false;
- for (int i = 0; i < needle.length(); i++) {
+ for (int i = 0; i < needle.length(); i++)
+ {
if (haystack[i] != needle[i])
return false;
}
@@ -22,19 +25,23 @@
}
template <typename T>
-void listDrop(QList<T> &list, int n) {
- for (; n; n--) {
+void listDrop(QList<T> &list, int n)
+{
+ for (; n; n--)
+ {
list.removeFirst();
}
}
template <typename T>
-QList<T> listSlice(QList<T> &list, int from, int to) {
+QList<T> listSlice(QList<T> &list, int from, int to)
+{
QList<T> prime;
// I guess we'll just panic if it's too long
// TODO: ERROR HANDLING
- for (int i = 0; i < to - from; i++) {
+ for (int i = 0; i < to - from; i++)
+ {
prime.append(list[from + i]);
}
diff --git a/Parser.cpp b/Parser.cpp
new file mode 100644
index 0000000..2d6b992
--- /dev/null
+++ b/Parser.cpp
@@ -0,0 +1,193 @@
+#include "Parser.h"
+
+#include <QDebug>
+
+Parser::Parser(QString input)
+{
+ _input = input;
+}
+
+QChar Parser::peek()
+{
+ if (atEnd())
+ return 0;
+
+ return _input[_pos];
+}
+
+QChar Parser::get()
+{
+ return _input[_pos++];
+}
+
+bool Parser::atEnd()
+{
+ return _pos >= _input.length();
+}
+
+void Parser::skip()
+{
+ while (peek().isSpace())
+ get();
+}
+
+bool Parser::parseSymbol(AstNode *node)
+{
+ skip();
+
+ if (peek().isLetter())
+ {
+ *node = AstNode(get());
+ return true;
+ }
+
+ return false;
+}
+
+bool Parser::parseIdentifier(AstNode *node)
+{
+ skip();
+
+ QString buffer;
+
+ if (peek().isUpper())
+ {
+ while (peek().isLetter() || peek() == '-' || peek() == '_' || peek().isNumber())
+ {
+ buffer += get();
+ }
+
+ *node = AstNode(buffer);
+ return true;
+ }
+
+ return false;
+}
+
+bool Parser::parseNumber(AstNode *node)
+{
+ skip();
+
+ QString buffer;
+
+ if (peek().isDigit())
+ {
+ while (peek().isDigit())
+ buffer += get();
+
+ *node = AstNode(buffer.toInt());
+ return true;
+ }
+
+ return false;
+}
+
+bool Parser::parseVariable(AstNode *node)
+{
+ skip();
+
+ int pos = _pos;
+
+ if (peek() == 's' || peek() == 'e' || peek() == 't')
+ {
+ char type = get().toLatin1();
+
+ if (peek() == '.')
+ {
+ get();
+
+ AstNode identNode;
+
+ if (parseIdentifier(&identNode))
+ {
+ *node = AstNode(type, identNode.name());
+ return true;
+ }
+ }
+ }
+
+ _pos = pos;
+ return false;
+}
+
+bool Parser::parseOne(AstNode *node)
+{
+ return parseFunction(node) ||
+ parseVariable(node) ||
+ parseNumber(node) ||
+ parseIdentifier(node) ||
+ parseSymbol(node) ||
+ parseParens(node);
+}
+
+QList<AstNode> Parser::parseMany()
+{
+ QList<AstNode> nodes;
+ AstNode next;
+
+ while (parseOne(&next))
+ {
+ nodes.append(next);
+ }
+
+ return nodes;
+}
+
+bool Parser::parseParens(AstNode *node)
+{
+ skip();
+
+ int pos = _pos;
+
+ if (peek() != '(')
+ return false;
+
+ get();
+
+ QList<AstNode> many = parseMany();
+ *node = AstNode(many);
+
+ skip();
+ if (peek() != ')')
+ {
+ _pos = pos;
+ return false;
+ }
+
+ get();
+
+ return true;
+}
+
+bool Parser::parseFunction(AstNode *node)
+{
+ skip();
+
+ int pos = _pos;
+
+ if (peek() != '<')
+ return false;
+
+ get();
+
+ AstNode head;
+ if (!parseIdentifier(&head))
+ {
+ _pos = pos;
+ return false;
+ }
+
+ QList<AstNode> body = parseMany();
+ *node = AstNode(head.name(), body);
+
+ skip();
+ if (peek() != '>')
+ {
+ _pos = pos;
+ return false;
+ }
+
+ get();
+
+ return true;
+}
diff --git a/Parser.h b/Parser.h
new file mode 100644
index 0000000..52cafac
--- /dev/null
+++ b/Parser.h
@@ -0,0 +1,30 @@
+#pragma once
+
+#include <QString>
+
+#include "AstNode.h"
+
+class Parser
+{
+public:
+ explicit Parser(QString input);
+
+ QChar peek();
+ QChar get();
+ bool atEnd();
+
+ void skip();
+
+ bool parseSymbol(AstNode *node);
+ bool parseIdentifier(AstNode *node);
+ bool parseNumber(AstNode *node);
+ bool parseVariable(AstNode *node);
+ bool parseParens(AstNode *node);
+ bool parseFunction(AstNode *node);
+ QList<AstNode> parseMany();
+ bool parseOne(AstNode *node);
+
+private:
+ int _pos = 0;
+ QString _input;
+};
diff --git a/Token.cpp b/Token.cpp
index 4ebf058..56c32a9 100644
--- a/Token.cpp
+++ b/Token.cpp
@@ -1,103 +1,3 @@
#include "Token.h"
-#include <QDebug>
-#include <utility>
-
-Token::Token(const Token &other) {
- *this = other;
-}
-
-Token::Token(QChar symbol) {
- _type = SYM;
- _charVal = symbol;
-}
-
-Token::Token(QString &&identifier) {
- _type = IDENT;
- _stringVal = identifier;
-}
-
-Token::Token(QList<Token> parenthesized) {
- _type = PAREN;
- _listVal = std::move(parenthesized);
-}
-
-Token::Token(char varType, const QString &&name) {
- _type = VAR;
- _charVal = varType;
- _stringVal = name;
-}
-
-bool Token::isSym() const {
- return _type == SYM;
-}
-
-bool Token::isIdent() const {
- return _type == IDENT;
-}
-
-bool Token::isParen() const {
- return _type == PAREN;
-}
-
-bool Token::isVar() const {
- return _type == VAR;
-}
-
-Token::Token() : Token("Null") {
-}
-
-bool Token::operator==(const Token &other) const {
- return _type == other._type
- && _stringVal == other._stringVal
- && _charVal == other._charVal
- && _listVal == other._listVal;
-}
-
-QList<Token> Token::parenContent() {
- if (isParen()) {
- return _listVal;
- } else {
- return {};
- }
-}
-
-char Token::varType() const {
- return _charVal.toLatin1();
-}
-
-const QString &Token::name() const {
- return _stringVal;
-}
-
-bool Token::operator!=(const Token &other) const {
- return !(this->operator==(other));
-}
-
-Token::operator QString() const {
- if (isIdent())
- return _stringVal;
- if (isSym())
- return _charVal;
- if (isVar())
- return QString(_charVal) + "." + _stringVal;
- if (isParen()) {
- QStringList parts;
- for (const Token &tok : _listVal) {
- parts.append(static_cast<QString>(tok));
- }
-
- return "(" + parts.join(" ") + ")";
- }
-
- return "Null";
-}
-
-int Token::type() const {
- return _type;
-}
-
-QString Token::typeToString(int type) {
- static const QString typeNames[] = {"SYMBOL", "IDENT", "PAREN", "VAR"};
- return typeNames[type];
-}
+// Nothing, aparently
diff --git a/Token.h b/Token.h
index 4835de0..76020ef 100644
--- a/Token.h
+++ b/Token.h
@@ -3,44 +3,196 @@
#include <QList>
#include <QChar>
-class Token {
+template <typename T>
+class TokenBase
+{
public:
- Token();
- Token(const Token &other);
+ TokenBase();
+ TokenBase(const T &other);
- explicit Token(QChar symbol);
- explicit Token(QString &&identifier);
- explicit Token(QList<Token> parenthesized);
- Token(char varType, const QString &&name);
+ explicit TokenBase(QChar symbol);
+ explicit TokenBase(QString identifier);
+ explicit TokenBase(QList<T> parenthesized);
+ TokenBase(char varType, const QString name);
- bool operator ==(const Token &other) const;
- bool operator !=(const Token &other) const;
+ bool operator==(const T &other) const;
+ bool operator!=(const T &other) const;
bool isSym() const;
bool isIdent() const;
bool isParen() const;
bool isVar() const;
- QList<Token> parenContent();
+ QList<T> parenContent();
char varType() const;
const QString &name() const;
operator QString() const;
- enum Type {
- SYM, IDENT, PAREN, VAR,
+ enum
+ {
+ SYM,
+ IDENT,
+ PAREN,
+ VAR,
+ TOKEN_TYPE_LAST,
};
static QString typeToString(int type);
int type() const;
-private:
+protected:
int _type = 0;
QString _stringVal = "";
- QList<Token> _listVal;
+ QList<T> _listVal;
QChar _charVal = 0;
};
+class Token : public TokenBase<Token>
+{
+public:
+ using TokenBase::TokenBase;
+};
+
using LTok = QList<Token>;
+
+template <typename T>
+TokenBase<T>::TokenBase(const T &other)
+{
+ _type = other._type;
+ _stringVal = other._stringVal;
+ _listVal = other._listVal;
+ _charVal = other._charVal;
+}
+
+template <typename T>
+TokenBase<T>::TokenBase(QChar symbol)
+{
+ _type = SYM;
+ _charVal = symbol;
+}
+
+template <typename T>
+TokenBase<T>::TokenBase(QString identifier)
+{
+ _type = IDENT;
+ _stringVal = identifier;
+}
+
+template <typename T>
+TokenBase<T>::TokenBase(QList<T> parenthesized)
+{
+ _type = PAREN;
+ _listVal = std::move(parenthesized);
+}
+
+template <typename T>
+TokenBase<T>::TokenBase(char varType, const QString name)
+{
+ _type = VAR;
+ _charVal = varType;
+ _stringVal = name;
+}
+
+template <typename T>
+bool TokenBase<T>::isSym() const
+{
+ return _type == SYM;
+}
+
+template <typename T>
+bool TokenBase<T>::isIdent() const
+{
+ return _type == IDENT;
+}
+
+template <typename T>
+bool TokenBase<T>::isParen() const
+{
+ return _type == PAREN;
+}
+template <typename T>
+bool TokenBase<T>::isVar() const
+{
+ return _type == VAR;
+}
+
+template <typename T>
+TokenBase<T>::TokenBase() : TokenBase("Null")
+{
+}
+
+template <typename T>
+bool TokenBase<T>::operator==(const T &other) const
+{
+ return _type == other._type && _stringVal == other._stringVal && _charVal == other._charVal && _listVal == other._listVal;
+}
+
+template <typename T>
+QList<T> TokenBase<T>::parenContent()
+{
+ if (isParen())
+ {
+ return _listVal;
+ }
+ else
+ {
+ return {};
+ }
+}
+
+template <typename T>
+char TokenBase<T>::varType() const
+{
+ return _charVal.toLatin1();
+}
+
+template <typename T>
+const QString &TokenBase<T>::name() const
+{
+ return _stringVal;
+}
+
+template <typename T>
+bool TokenBase<T>::operator!=(const T &other) const
+{
+ return !(this->operator==(other));
+}
+
+template <typename T>
+TokenBase<T>::operator QString() const
+{
+ if (isIdent())
+ return _stringVal;
+ if (isSym())
+ return _charVal;
+ if (isVar())
+ return QString(_charVal) + "." + _stringVal;
+ if (isParen())
+ {
+ QStringList parts;
+ for (const T &tok : _listVal)
+ {
+ parts.append(static_cast<QString>(tok));
+ }
+
+ return "(" + parts.join(" ") + ")";
+ }
+
+ return "Null";
+}
+
+template <typename T>
+int TokenBase<T>::type() const
+{
+ return _type;
+}
+
+template <typename T>
+QString TokenBase<T>::typeToString(int type)
+{
+ static const QString typeNames[] = {"SYMBOL", "IDENT", "PAREN", "VAR"};
+ return typeNames[type];
+}
diff --git a/main.cpp b/main.cpp
index ebf886f..fc9d547 100644
--- a/main.cpp
+++ b/main.cpp
@@ -3,89 +3,113 @@
#include "Matcher.h"
#include "Token.h"
+#include "AstNode.h"
+#include "Parser.h"
int g_numFailed = 0;
-void printResult(const QString &test, bool shouldBe, const MatchResult &result) {
- if (result.success != shouldBe) {
+void testMatch(const QString &test, bool shouldBe, const MatchResult &result)
+{
+ if (result.success != shouldBe)
+ {
g_numFailed++;
- qDebug() << "\nTEST FAILS:";
+ qDebug() << "\n\033[31mTEST FAILS:\033[0m";
qDebug() << "with context" << result.context;
}
- qDebug() << "MatchResult" << test << result.success;
+ qDebug() << "\033[36mMatchResult\033[0m" << test << result.success;
- if (result.success != shouldBe) {
+ if (result.success != shouldBe)
+ {
qDebug() << "";
}
}
-int testResults() {
- if (g_numFailed == 0) {
- qDebug() << "ALL TESTS SUCCEEDED";
- } else {
- qDebug() << g_numFailed << "TESTS FAILED";
+void testParse(QString string)
+{
+ Parser parser{string};
+
+ QList<AstNode> result = parser.parseMany();
+
+ qDebug() << "\033[36mParse\033[0m" << string << result;
+}
+
+int testResults()
+{
+ if (g_numFailed == 0)
+ {
+ qDebug() << "\033[32mALL TESTS SUCCEEDED\033[0m";
+ }
+ else
+ {
+ qDebug().nospace() << "\033[31m" << g_numFailed << " TESTS FAILED\033[0m";
}
return g_numFailed;
}
-void runTests() {
- printResult("a = a", true, match({Token('a')}, {Token('a')}, VarContext()));
+void testAllMatches()
+{
+ testMatch("a = a", true, match({Token('a')}, {Token('a')}, VarContext()));
- printResult("s.a = y", true, match({Token('y')}, {Token('s', "a")}, VarContext()));
+ testMatch("s.a = y", true, match({Token('y')}, {Token('s', "a")}, VarContext()));
LTok sameTwo = {Token('s', "a"), Token('s', "a")};
- printResult("s.a s.a = aa", true, match({Token('a'), Token('a')}, sameTwo, VarContext()));
- printResult("s.a s.a = ab", false, match({Token('a'), Token('b')}, sameTwo, VarContext()));
+ testMatch("s.a s.a = aa", true, match({Token('a'), Token('a')}, sameTwo, VarContext()));
+ testMatch("s.a s.a = ab", false, match({Token('a'), Token('b')}, sameTwo, VarContext()));
LTok sameStartEnd = {
- Token('s', "a"),
- Token('e', "middle"),
- Token('s', "a")
- };
- printResult("s.a e.middle s.a = aea", true,
- match({
- Token('a'), Token('e'), Token('a')
- }, sameStartEnd, VarContext()));
+ Token('s', "a"),
+ Token('e', "middle"),
+ Token('s', "a")};
+ testMatch("s.a e.middle s.a = aea", true,
+ match({Token('a'), Token('e'), Token('a')}, sameStartEnd, VarContext()));
- printResult("s.a e.middle s.a = aef Hi a", true,
- match({
- Token('a'), Token('e'), Token('f'), Token("Hi"), Token('a')
- }, sameStartEnd, VarContext()));
+ testMatch("s.a e.middle s.a = aef Hi a", true,
+ match({Token('a'), Token('e'), Token('f'), Token("Hi"), Token('a')}, sameStartEnd, VarContext()));
- printResult("s.a e.middle s.a = aef Hi c", false,
- match({
- Token('a'), Token('e'), Token('f'), Token("Hi"), Token('c')
- }, sameStartEnd, VarContext()));
+ testMatch("s.a e.middle s.a = aef Hi c", false,
+ match({Token('a'), Token('e'), Token('f'), Token("Hi"), Token('c')}, sameStartEnd, VarContext()));
LTok parenthesized = {
- Token(LTok({
- Token('s', "a")
- })),
- Token('e', "Middle"),
- Token('s', "a"),
+ Token(LTok({Token('s', "a")})),
+ Token('e', "Middle"),
+ Token('s', "a"),
};
LTok parenTest1 = {
- Token(LTok({
- Token('y')
- })),
- Token('f'),
- Token("MiddleStuff"),
- Token('y')
- };
+ Token(LTok({Token('y')})),
+ Token('f'),
+ Token("MiddleStuff"),
+ Token('y')};
- printResult("(s.a) e.Middle s.a = (y)f MiddleStuff y", true,
+ testMatch("(s.a) e.Middle s.a = (y)f MiddleStuff y", true,
match(parenTest1, parenthesized, VarContext()));
- printResult("(a) = (a)", true,
+ testMatch("(a) = (a)", true,
match({Token({Token('a')})}, {Token({Token('a')})}, VarContext()));
}
-int main(int argc, char *argv[]) {
+void testAllParses()
+{
+ testParse("all symbols");
+ testParse("Identifier symbols Identifier");
+ testParse("s.A");
+ testParse("(s.A) Variable-quoted");
+ testParse("<Func-name a b (c)>");
+ testParse("<Prout hi>");
+ testParse("(Prout hi)");
+ testParse("(<Prout hi>)");
+ testParse("<If T Then (<Prout hi>) Else (<Prout sorry>)>");
+}
+
+int main(int argc, char *argv[])
+{
QCoreApplication a(argc, argv);
- runTests();
+ testAllMatches();
+ qDebug() << "";
+ testAllParses();
+ qDebug() << "";
return testResults();
}
diff --git a/notes.txt b/notes.txt
new file mode 100644
index 0000000..d101e9c
--- /dev/null
+++ b/notes.txt
@@ -0,0 +1,8 @@
+export QT_LOGGING_RULES="*.debug=true"
+
+
+OPTIMIZATION POSSIBILITIES:
+
+ When parsing e.* variables check the min length of the remaining tokens. If
+ we have `e.1 s.2' for instance, we can tell right away how long `e.1' wil
+ have to be.