Skip to content

Instantly share code, notes, and snippets.

@veryjos
Last active November 28, 2017 03:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save veryjos/a8050ff80f78f6465c7e37e2a2fb2f10 to your computer and use it in GitHub Desktop.
Save veryjos/a8050ff80f78f6465c7e37e2a2fb2f10 to your computer and use it in GitHub Desktop.
Success #stdin #stdout 0s 16072KB
76
69
FooBar
hey
there bud
#include <iostream>
#include <vector>
#include <stack>
#include <string>
/**
* Variant type to stick in the stack
**/
enum VariantType {
VariantType_None,
VariantType_Int,
VariantType_String
};
class Variant {
public:
Variant(int num) : num(num), type(VariantType_Int) {
};
Variant(std::string str) : str(str), type(VariantType_String) {
};
VariantType GetType() {
return type;
};
int AsInt() {
return num;
};
std::string AsString() {
return str;
};
private:
VariantType type;
int num;
std::string str;
};
/**
* Base node type for syntax tree
**/
class Node {
public:
std::vector<Node*> children;
virtual void Accept(std::stack<Variant>* stack) {
// Visit each child (this will be postorder)
for (auto child : children) {
child->Accept(stack);
}
};
};
/**
* Node which prints out the top of the stack
**/
class PrintNode : public Node {
public:
virtual void Accept(std::stack<Variant>* stack) override {
// If empty do nothing
if (children.empty())
return;
// Visit lefthand side
children[0]->Accept(stack);
// Pop the last value off the stack (added by children)
// and evaluate them. Push the result on the stack.
Variant value = stack->top();
stack->pop();
switch (value.GetType()) {
case VariantType_Int:
printf("%d\n", value.AsInt());
break;
case VariantType_String:
printf("%s\n", value.AsString().c_str());
break;
};
// Visit the rest of the children
for (int i=1;i<children.size();++i) {
children[i]->Accept(stack);
}
};
};
/**
* Node for adding two NumberNodes
**/
class AddNode : public Node {
public:
void Accept(std::stack<Variant>* stack) override {
// Visit the left node, then the right node
children[0]->Accept(stack);
children[1]->Accept(stack);
// Pop the last two values off the stack (added by children)
// and add them. Push the result on the stack
Variant rightHandSide = stack->top();
stack->pop();
Variant leftHandSide = stack->top();
stack->pop();
// Add them as ints
if (leftHandSide.GetType() == VariantType_Int &&
rightHandSide.GetType() == VariantType_Int) {
// Push the result
stack->push(Variant(leftHandSide.AsInt() + rightHandSide.AsInt()));
}
// Or as strings
else
if (leftHandSide.GetType() == VariantType_String &&
rightHandSide.GetType() == VariantType_String) {
// Push the result
stack->push(Variant(leftHandSide.AsString() + rightHandSide.AsString()));
}
};
};
/**
* Represents a number literal
**/
class NumberNode : public Node {
public:
NumberNode(int num) : value(num) {};
void Accept(std::stack<Variant>* stack) override {
stack->push(Variant(value));
};
int value;
};
/**
* Represents a string literal
**/
class StringNode : public Node {
public:
StringNode(std::string str) : value(str) {};
void Accept(std::stack<Variant>* stack) override {
stack->push(Variant(value));
};
std::string value;
};
int main() {
/////////////////////////////////
// Print
// /
// Add
// / \
// 1 Add
// / \
// 50 25
/////////////////////////////////
{
// Create a print node at root
auto printNode = new PrintNode();
// Do some math
auto addNodeOuter = new AddNode();
auto addNodeInner = new AddNode();
addNodeOuter->children.push_back(new NumberNode(1));
addNodeInner->children.push_back(new NumberNode(50));
addNodeInner->children.push_back(new NumberNode(25));
addNodeOuter->children.push_back(addNodeInner); // Righthand side is the inner node
// We want to print the result of this, so push the outer node
printNode->children.push_back(addNodeOuter);
// Start visiting the tree from the root print node
printNode->Accept(new std::stack<Variant>());
}
/////////////////////////////////
// Print
// /
// 69
/////////////////////////////////
{
// Create a print node at root
auto printNode = new PrintNode();
// Just stick a number there
printNode->children.push_back(new NumberNode(69));
// Start visiting the tree from the root print node
printNode->Accept(new std::stack<Variant>());
}
/////////////////////////////////
// Print
// /
// Add
// / \
// "Foo" "Bar"
/////////////////////////////////
{
// Create a print node at root
auto printNode = new PrintNode();
// Just add two string literals
auto addNode = new AddNode();
addNode->children.push_back(new StringNode("Foo"));
addNode->children.push_back(new StringNode("Bar"));
// Add to the print node's children
printNode->children.push_back(addNode);
// Start visiting the tree from the root print node
printNode->Accept(new std::stack<Variant>());
}
/////////////////////////////////
// Print
// / \
// "hey " Print
// /
// Add
// / \
// "there " "bud"
/////////////////////////////////
{
// Create a print node at root
auto printNode = new PrintNode();
printNode->children.push_back(new StringNode("hey "));
// Create a print node for the righthand side
auto printNodeRight = new PrintNode();
// Just add two string literals
auto addNode = new AddNode();
addNode->children.push_back(new StringNode("there "));
addNode->children.push_back(new StringNode("bud"));
// Add to the right print node's children
printNodeRight->children.push_back(addNode);
// And finally add the right print node to the root print node's right side
printNode->children.push_back(printNodeRight);
// Start visiting the tree from the root print node
printNode->Accept(new std::stack<Variant>());
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment