At ``unittest // ???`` you see what's my problem I don't understand.

What I already done:
- Removed ``nothrow``
- Using ``try-catch``

```d
module mitgedanken.parser;

import std.typecons : Tuple;
import std.container : Array;
import std.conv : to;
import std.traits : isSomeString;
import std.string;


struct Symbol
{
    string str;

@property ulong length() const @safe pure nothrow => this.str.length; @property bool empty() const @safe pure nothrow => (this.str.length == 0);

    static Symbol asEmpty() @safe pure nothrow
        => Symbol("");

    string toString() const @safe pure nothrow
        => this.str;

    ulong opDollar()
        => this.length;

    T opCast(T : string)() const
        => this.str;

    auto opAssign(T)(T value) if (isSomeString!T)
    {
        this.str = value;
        return this;
    }

    auto opBinary(string op : "~")(string rhs)
    {
        Symbol symbol = Symbol(this.str ~ rhs);
        return symbol;
    }

auto opOpAssign(string op = "~=", T)(T value) if (isSomeString!T)
    {
        this.str ~= value;
        return this;
    }
}

alias NodeRef = NullableNodeRef;
alias RootRef = NodeRef;

alias TreeRef = Tree*;

enum Kind : string
{
    _Undefined_ = "undefined",
    Terminal    = "terminal",
    Leaf        = "leaf",
    Root        = "root",
}

struct NullableNodeRef
{
    private Node* _node;
    alias node = _node;

@property bool isNull() const pure @safe nothrow => (this._node is null); @property Node* get() pure @safe nothrow => this._node;

    @property string getString(const string stringIfNull) const
        => this.isNull ? stringIfNull : this._node.repr();

    this (Node node) nothrow
    {
        this._node = &node;
    }

    this (Node* nodeRef) nothrow
    {
        this._node = nodeRef;
    }

    auto opDispatch(string member)() const
        => mixin("this._node." ~ member);

    auto opDispatch(string member)()
        => mixin("this._node." ~ member);

    bool opEqual(Object other)
        => *this._node == other;

    T opCast(T : Node*)() const
        => this._node;

    static nodeRef(ref Node node)
        => NodeRef(node);
}

NullableNodeRef nullableRef(Node node) nothrow
    => NullableNodeRef(node);

NullableNodeRef nullableRef(Node* node) nothrow
    => NullableNodeRef(node);

interface Representable
{
    string repr();
}

class Node : Representable
{
private:
    int     _precedence;
    TreeRef _tree;
    Kind    _kind;

    Symbol  _symbol;
    NodeRef _root;
    NodeRef _left;
    NodeRef _right;

public:
@property TreeRef tree() @safe pure nothrow => this._tree; @property Symbol symbol() @safe pure nothrow => this._symbol; @property int precedence() @safe pure nothrow => this._precedence; @property NodeRef root() @safe pure nothrow => this._root; @property NodeRef left() @safe pure nothrow => this._left; @property NodeRef right() @safe pure nothrow => this._right; @property Kind kind() @safe pure nothrow => this._kind;

@property bool terminates() const @safe pure nothrow => !this.isLeaf();

    alias parent = root;

    @property void root(NodeRef nodeRef) @safe
    {
        if (!this._root.isNull)
            throw new Error("Root node already exists");

        this._root = nodeRef;
    }

    @property void left(NodeRef nodeRef) @safe
    {
        if (!this._left.isNull)
            throw new Error("Left node already exists");

        this._left = nodeRef;
    }

    @property void right(NodeRef nodeRef) @safe
    {
        if (!this._right.isNull)
            throw new Error("Right node already exists");

        this._right = nodeRef;
    }

    this(
        TreeRef tree,
        Symbol  symbol,
        int     precedence,
        NodeRef root,
        NodeRef left  = NodeRef.init,
        NodeRef right = NodeRef.init
    )
    {
        this._tree       = tree;
        this._symbol     = symbol;
        this._precedence = precedence;
        this._root       = root;
        this._left       = left;
        this._right      = right;

        _setKind();
    }

this(TreeRef tree, Symbol symbol, int precedence, NodeRef root)
    {
        this._tree       = tree;
        this._symbol     = symbol;
        this._precedence = precedence;
        this._root       = root;

        _setKind();
    }

    this(TreeRef tree, Symbol symbol, int precedence)
    {
        this._tree       = tree;
        this._symbol     = symbol;
        this._precedence = precedence;

        _setKind();
    }

bool isLeaf() const pure @safe nothrow => this.hasLeft() || this.hasRight(); bool isRoot() const pure @safe nothrow => this._root.isNull && this.isLeaf();

bool hasParent() const pure @safe nothrow => !this._root.isNull; bool hasLeft() const pure @safe nothrow => !this._left.isNull; bool hasRight() const pure @safe nothrow => !this._right.isNull;

    alias hasRoot = hasParent;

    string repr() const
    {
        string str = "";

        str ~= "\"" ~ this._symbol.str ~ "\"";
        str ~= "(";
        str ~= "prec="    ~ to!string(this._precedence);
        str ~= ", kind="  ~ this._kind;
        str ~= ", root="  ~ this._root.getString("<no root>");
str ~= ", left=" ~ this._left.getString("<no left leaf>"); str ~= ", right=" ~ this._right.getString("<no right leaf>");
        str ~= ")";

        return str;
    }

    private void _setKind() @safe pure nothrow
    {
        if (this.root.isNull)
            this._kind = Kind.Root;
        else if (!this._left.isNull || !this._right.isNull)
            this._kind = Kind.Leaf;
        else
            this._kind = Kind.Terminal;
    }

    //override string toString() const @safe pure nothrow
    //    => this.repr();

    T opCast(T : string)() const
        => this._symbol.str;

    T opCast(T : NodeRef)() const
        => nullableRef(this);

    auto opBinary(string op : "~")(string rhs)
    {
        Node node = new Node(
            this._tree,
            this._symbol ~ rhs,
            this._precedence,
            this._root,
            this._left,
            this._right
        );

        return node;
    }

    auto opBinary(string op : "~")(Node rhs)
    {
        Node node = new Node(
            this._tree,
            this._symbol ~ rhs.symbol.str,
            this._precedence,
            this._root,
            this._left,
            this._right
        );

        return node;
    }

    auto opBinary(string op : "~")(NodeRef rhs)
    {
        Node node = new Node(
            this._tree,
            this._symbol ~ rhs.symbol.str,
            this._precedence,
            this._root,
            this._left,
            this._right
        );

        return NodeRef(node);
    }

    auto opBinary(string op : "~")(NodeRef rhs)
    {
        Node node = new Node(
            this._tree,
            this._symbol ~ rhs.symbol.str,
            this._precedence,
            this._root,
            this._left,
            this._right
        );

        return NodeRef(node);
    }

    override bool opEquals(Object other) const
    {
        if (is(other == Node))
            return false;

        const Node n = cast(Node) other;
        return (n.repr() == this.repr());
    }

    bool opEquals(typeof(null) other) const
        => this._kind != Kind._Undefined_;
}

alias Root = Node;

final class Tree : Representable
{
    private NodeRef _root;
    private ulong   _count;
    private NodeRef _current;

    @property NodeRef root()  @safe pure nothrow => this._root;
    @property ulong   count() @safe pure nothrow => this._count;

    @property void root(NodeRef nodeRef)
    {
        this._root = nodeRef;
    }

    void incrementCount(uint byAmountOf = 1)
    {
        this._count += byAmountOf;
    }

    this(Node* root)
    {
        this._root  = NodeRef(root);
        this._count = 0;
    }

    this()
    {
        this._root  = NodeRef.init;
        this._count = 0;
    }

    bool hasRoot() => !this._root.isNull;

    string repr()
    {
        import std.stdio;

        string tree = "";
        Node* curr = this._root.get;

        if (curr.isRoot)
            return "";

        while (!curr.terminates)
        {
            tree ~= curr.repr();

            if (curr.hasLeft())
                curr = curr.left.get;
            else if (curr.hasRight())
                curr = curr.right.get;
        }

        if (tree == "" || tree == "\n")
            return "";

        return tree.strip("\n");
    }

    alias toString = repr;
}

unittest // ???
{
    import std.stdio;

    Tree tree = new Tree();
    TreeRef treeRef = &tree;

    Node op  = new Node(treeRef, Symbol("+"), 0);
    // That's fine, the root is displayed
    Node one = new Node(treeRef, Symbol("1"), 0, nullableRef(op));
    Node two = new Node(treeRef, Symbol("2"), 0, nullableRef(op));

    //(1) Execution ends
    op.left  = nullableRef(&one);
    op.right = nullableRef(&two);

    //(2) Execution ends after this, if it is at (1) position
    writeln(two.repr());

    writeln(one.repr());
    writeln(op.repr());

    if (!treeRef.hasRoot())
        treeRef.root = nullableRef(&op);

    //writeln(*treeRef);
    writeln(tree.root.get.hasRight());
}

int main(string[] _)
{
    return 0;
}
```
  • Why stops this c... mitgedanken via Digitalmars-d-learn
    • Re: Why sto... Richard (Rikki) Andrew Cattermole via Digitalmars-d-learn
    • Re: Why sto... Dejan Lekic via Digitalmars-d-learn
      • Re: Why... mitgedanken via Digitalmars-d-learn
      • Re: Why... 0xEAB via Digitalmars-d-learn
        • Re:... mitgedanken via Digitalmars-d-learn
          • ... Dejan Lekic via Digitalmars-d-learn
            • ... mitgedanken via Digitalmars-d-learn
              • ... mitgedanken via Digitalmars-d-learn
                • ... mitgedanken via Digitalmars-d-learn
                • ... mitgedanken via Digitalmars-d-learn

Reply via email to