private static Property MakeProperty(
            ChainableWithArgsContext ctx,
            bool optional,
            bool rootedDynamic)
        {
            var name = ctx.chainableIdent().GetText();

            if (ctx.lp == null)
            {
                return(optional | rootedDynamic ? (Property) new DynamicSimpleProperty(name) : new SimpleProperty(name));
            }

            var func = ctx.libFunctionArgs().libFunctionArgItem()[0];
            var key  = StringValue.ParseString(func.GetText());

            return(optional ? (Property) new DynamicMappedProperty(name, key) : new MappedProperty(name, key));
        }
        private static Property WalkProp(ChainableWithArgsContext ctx, ChainableAtomicWithOptContext nextOrNull, bool optional, bool rootedDynamic)
        {
            if (nextOrNull == null)
            {
                return(MakeProperty(ctx, optional, rootedDynamic));
            }

            var name = ctx.chainableIdent().GetText();

            if (nextOrNull.chainableAtomic().chainableArray() != null)
            {
                var indexText = nextOrNull.chainableAtomic().chainableArray().expression(0).GetText();
                var index     = int.Parse(indexText);
                optional |= nextOrNull.q != null;
                return(optional ? (Property) new DynamicIndexedProperty(name, index) : new IndexedProperty(name, index));
            }
            else
            {
                return(MakeProperty(ctx, optional, rootedDynamic));
            }
        }