Add standard stack manipulation functions
diff --git a/AstNode.h b/AstNode.h
index b10872a..1cf66d4 100644
--- a/AstNode.h
+++ b/AstNode.h
@@ -7,7 +7,7 @@
 public:
     using TokenBase::TokenBase;
 
-    explicit AstNode(QString function, QList<AstNode> args);
+    AstNode(QString function, QList<AstNode> args);
 
     enum
     {
diff --git a/Evaluator.cpp b/Evaluator.cpp
index b52b843..5177fe5 100644
--- a/Evaluator.cpp
+++ b/Evaluator.cpp
@@ -2,6 +2,7 @@
 #include "Function.h"
 #include "Matcher.h"
 #include "VarContext.h"
+#include "PPrint.h"
 
 #include <QDebug>
 
@@ -38,6 +39,40 @@
 
 Evaluator::Evaluator()
 {
+    Function buryFn("Br");
+    buryFn.addNativeSentence("s.Name '=' e.Expr", [this](VarContext args)
+    {
+        Token name = args.singleVar("Name");
+        if (name.type() != Token::IDENT)
+            rtError("Invalid argument", "First argument to <Br> must be an identifier, received " + pprint(name));
+
+        bury(name.name(), args.expressionVar("Expr"));
+
+        return QList<Token>();
+    });
+    addFunction(buryFn);
+
+    Function digFn("Dg");
+    digFn.addNativeSentence("s.Name", [this](VarContext args)
+    {
+        Token name = args.singleVar("Name");
+        if (name.type() != Token::IDENT)
+            rtError("Invalid argument", "First argument to <Dg> must be an identifier, received " + pprint(name));
+
+        return dig(name.name());
+    });
+    addFunction(digFn);
+
+    Function copyFn("Cp");
+    copyFn.addNativeSentence("s.Name", [this](VarContext args)
+    {
+        Token name = args.singleVar("Name");
+        if (name.type() != Token::IDENT)
+            rtError("Invalid argument", "First argument to <Cp> must be an identifier, received " + pprint(name));
+
+        return copy(name.name());
+    });
+    addFunction(copyFn);
 }
 
 void Evaluator::addFunction(Function func)
@@ -132,7 +167,7 @@
 
 		if (sentence.isExternal())
 		{
-			return RuntimeResult(sentence.externResult(args));
+            return RuntimeResult(sentence.externResult(res));
 		}
 
 		QList<Token> final;
@@ -148,5 +183,52 @@
 		return RuntimeResult(final);
 	}
 
-	return RuntimeResult("Function " + name + " had no matching sentences for input");
+    return RuntimeResult("Function " + name + " had no matching sentences for input");
+}
+
+QList<Token> Evaluator::dig(QString name)
+{
+    if (_vars.contains(name))
+    {
+        QList<Token> value = _vars[name].pop();
+
+        if (_vars[name].empty())
+        {
+            _vars.remove(name);
+        }
+
+        return value;
+    }
+    else
+    {
+        return {};
+    }
+}
+
+QList<Token> Evaluator::copy(QString name)
+{
+    if (_vars.contains(name))
+    {
+        return _vars[name].last();
+    }
+    else
+    {
+        return {};
+    }
+}
+
+void Evaluator::bury(QString name, QList<Token> expression)
+{
+    if (!_vars.contains(name))
+    {
+        _vars[name] = QStack<QList<Token>>();
+    }
+
+    _vars[name].push(expression);
+}
+
+void rtError(QString brief, QString details)
+{
+    eout("Runtime Error: " + brief);
+    eout(details);
 }
diff --git a/Evaluator.h b/Evaluator.h
index 5cc7851..afda18f 100644
--- a/Evaluator.h
+++ b/Evaluator.h
@@ -1,6 +1,7 @@
 #pragma once
 
 #include <QMap>
+#include <QStack>
 
 #include "Token.h"
 #include "AstNode.h"
@@ -36,4 +37,12 @@
 
 private:
 	QMap<QString, Function> _functions;
+    QMap<QString, QStack<QList<Token>>> _vars;
+
+protected:
+    QList<Token> dig(QString name);
+    QList<Token> copy(QString name);
+    void bury(QString name, QList<Token> expression);
 };
+
+void rtError(QString brief, QString details);
diff --git a/Function.cpp b/Function.cpp
index 39ac957..f28841f 100644
--- a/Function.cpp
+++ b/Function.cpp
@@ -36,9 +36,9 @@
 	return _native != nullptr;
 }
 
-QList<Token> Sentence::externResult(QList<Token> args) const
+QList<Token> Sentence::externResult(MatchResult args) const
 {
-	return _native(std::move(args));
+    return _native(args.context);
 }
 
 QList<Token> Sentence::pattern() const
diff --git a/Function.h b/Function.h
index 2cb862f..ca90113 100644
--- a/Function.h
+++ b/Function.h
@@ -2,8 +2,10 @@
 
 #include "Token.h"
 #include "AstNode.h"
+#include "VarContext.h"
+#include "Matcher.h"
 
-using SentenceResultFn = std::function<QList<Token> (QList<Token>)>;
+using SentenceResultFn = std::function<QList<Token> (VarContext)>;
 
 class Sentence {
 public:
@@ -13,7 +15,7 @@
 	Sentence(QList<Token> pattern, SentenceResultFn result);
 
 	bool isExternal() const;
-	QList<Token> externResult(QList<Token> args) const;
+    QList<Token> externResult(MatchResult args) const;
 
 	QList<Token> pattern() const;
 	QList<AstNode> result() const;
diff --git a/PPrint.cpp b/PPrint.cpp
index 986c38c..de43582 100644
--- a/PPrint.cpp
+++ b/PPrint.cpp
@@ -24,3 +24,8 @@
 
     return val.message() + " at " + val.pos() + "\n" + highlighted;
 }
+
+void eout(QString string)
+{
+    QTextStream(stderr) << string << '\n';
+}
diff --git a/PPrint.h b/PPrint.h
index 5212334..6298d6b 100644
--- a/PPrint.h
+++ b/PPrint.h
@@ -10,11 +10,11 @@
 template <typename T>
 QString pprint(T val);
 
-template <>
-QString pprint<Token>(Token val);
+//template <>
+//QString pprint<Token>(Token val);
 
-template <>
-QString pprint<AstNode>(AstNode val);
+//template <>
+//QString pprint<AstNode>(AstNode val);
 
 template <typename T>
 QString pprint(QList<T> val)
@@ -36,3 +36,4 @@
 QString pprint(ParseResult val, const Parser &parser);
 
 void sout(QString string);
+void eout(QString string);
diff --git a/Parser.cpp b/Parser.cpp
index 41f6727..6ce62fa 100644
--- a/Parser.cpp
+++ b/Parser.cpp
@@ -196,19 +196,27 @@
 template <typename T>
 ParseResult Parser::parseMany(QList<T> *list)
 {
-    QList<T> nodes;
+    QList<T> nodes, string;
     T next;
-	ParseResult ret;
+    ParseResult ret, stringRet;
 
-    while ((ret = parseOne(&next)))
+    while ((ret = parseOne(&next)) || (stringRet = parseString(&string)))
     {
-        nodes.append(next);
+        if (ret)
+            nodes.append(next);
+        else if (stringRet)
+            nodes.append(string);
+
+        // So that we can check if anything was incomplete recently at the end
+        ret = stringRet = false;
     }
 
 	*list = nodes;
 
 	if (ret.status() == ParseResult::INCOMPLETE)
 		return ret;
+    else if (stringRet.status() == ParseResult::INCOMPLETE)
+        return ret;
 	else
 		return true;
 }
@@ -423,3 +431,47 @@
 {
     return QString::number(line) + ":" + QString::number(lineOffset);
 }
+
+template <typename T>
+ParseResult Parser::parseString(QList<T> *list)
+{
+    skip();
+
+    ParsePos pos = save();
+
+    if (peek() != '\'')
+        return false;
+
+    get();
+
+    list->clear();
+
+    while (peek() != 0 && peek() != '\'')
+    {
+        QChar c = get();
+        if (c == '\\')
+        {
+            QChar next = get();
+            QString conversions = "''n\nt\tr\r";
+
+            for (int i = 0; i < conversions.size(); i += 2)
+            {
+                if (next == conversions[i])
+                    list->append(T(conversions[i + 1]));
+            }
+        }
+        else
+        {
+            list->append(T(c));
+        }
+    }
+
+    if (get() == 0)
+    {
+        ParseResult ret(ParseResult::INCOMPLETE, "Expected ' before end of input", save());
+        reset(pos);
+        return ret;
+    }
+
+    return true;
+}
diff --git a/Parser.h b/Parser.h
index 5d87a2b..102a3c3 100644
--- a/Parser.h
+++ b/Parser.h
@@ -76,6 +76,9 @@
     ParseResult parseMany(QList<T> *list);
 
     template <typename T>
+    ParseResult parseString(QList<T> *list);
+
+    template <typename T>
     ParseResult parseOne(T *node);
 
     ParseResult parseSentence(Sentence *sentence);
diff --git a/StdLib.cpp b/StdLib.cpp
index 0ad7887..5d6bf6a 100644
--- a/StdLib.cpp
+++ b/StdLib.cpp
@@ -3,15 +3,17 @@
 
 StdLib::StdLib()
 {
-	_print.addNativeSentence("e.Expr", [](QList<Token> args)
+    _print.addNativeSentence("e.Expr", [](VarContext args)
 	{
-		sout(pprint(args));
-		return args;
+        auto expr = args.expressionVar("Expr");
+        sout(pprint(args.expressionVar("Expr")));
+        return expr;
 	});
 
-	_prout.addNativeSentence("e.Expr", [](QList<Token> args)
+    _prout.addNativeSentence("e.Expr", [](VarContext args)
 	{
-		sout(pprint(std::move(args)));
+        auto expr = args.expressionVar("Expr");
+        sout(pprint(expr));
 		return QList<Token>();
 	});
 }
diff --git a/VarContext.h b/VarContext.h
index 5e580b3..6e5ea13 100644
--- a/VarContext.h
+++ b/VarContext.h
@@ -4,7 +4,8 @@
 #include <QDebug>
 #include "Token.h"
 
-class VarContext {
+class VarContext
+{
 public:
     VarContext() = default;
     VarContext(VarContext const &other)  noexcept;
@@ -19,7 +20,8 @@
     friend QDebug &operator <<(QDebug &debug, const VarContext &ctx);
 
 private:
-    struct Var {
+    struct Var
+    {
         Var() = default;
 
         char t = 0;
@@ -30,4 +32,4 @@
     QMap<QString, Var> _vars;
 };
 
-QDebug &operator <<(QDebug &debug, const VarContext &ctx);
\ No newline at end of file
+QDebug &operator <<(QDebug &debug, const VarContext &ctx);
diff --git a/main.cpp b/main.cpp
index ce9f435..7f1a3ad 100644
--- a/main.cpp
+++ b/main.cpp
@@ -83,7 +83,7 @@
 	}
 
 end:
-	qDebug() << "\033[36mEvaluate\033[0m" << function << expression << "->" << result;
+    qDebug() << "\033[36mEvaluate\033[0m" << function << expression << "->" << pprint(result);
 }
 
 void testEval(QString function, QString expression, QList<Token> expected)
@@ -91,6 +91,11 @@
 	testEval(function, expression, pprint(expected));
 }
 
+void testEval(QString expression, QString expected)
+{
+    testEval("", expression, expected);
+}
+
 void testMatch(const QString &test, bool shouldBe, const MatchResult &result)
 {
     if (result.success != shouldBe)
@@ -236,6 +241,8 @@
 	testParseAst("123", {AstNode("123", 10)});
 	testParseAst("12 00", {AstNode::fromInteger(12), AstNode::fromInteger(0)});
     testParseAst("s.A s.B", {AstNode('s', "A"), AstNode('s', "B")});
+    testParseAst("a '=' b", {AstNode('a'), AstNode('='), AstNode('b')});
+    testParseAst("'This\\'<>#$@#^%\\n' 'another $3543543'");
 }
 
 void testAllFunctionDefs()
@@ -248,6 +255,8 @@
 {
 	testEval("First {s.A e.Rest = s.A;}", "<First hello>", "h");
 	testEval("Number { = 123; }", "<Number>", QList<Token>{Token::fromInteger(123)});
+    testEval("<Br Name '=' Jim> <Dg Name>", "Jim");
+    testEval("<Br A '=' hello> <Br A '=' 'good bye'> <Dg A> <Dg A>", "'good byehello'");
 }
 
 int main(int argc, char *argv[])