Why stops this code

mitgedanken sara.dolores.tasche at gmail.com
Sat Apr 25 18:59:41 UTC 2026


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;
}
```


More information about the Digitalmars-d-learn mailing list