src/Leevel/View/Parser.php
protected function positionRelative(array $value, array $beyond): string
    {
        /*
         * 第一个匹配的标签在第二个前面
         * 条件：第一个结束字节位置 <= 第二个开始位置
         */

        /*
         * ======= start =======
         *
         * {if}
         * value
         * {/if}
         *
         * {for}
         * beyond
         * {/for}
         *
         * ======== end =======
         */
        if ($value['end'] <= $beyond['start']) {
            return 'front';
        }

        /*
         * 第一个匹配的标签在第二个后面
         * 条件：第一个开始字节位置 >= 第二个结束位置
         */

        /*
         * ======= start =======
         *
         * {for}
         * beyond
         * {/for}
         *
         * {if}
         * value
         * {/if}
         *
         * ======== end =======
         */
        if ($value['start'] >= $beyond['end']) {
            return 'behind';
        }

        /*
         * 第一个匹配的标签在第二个里面
         * 条件：第一个开始字节位置 >= 第二个开始位置
         */

        /*
         * ======= start =======
         *
         * {for}
         * beyond
         *
         * {if}
         * value
         * {/if}
         *
         * {/for}
         *
         * ======== end =======
         */
        if ($value['start'] >= $beyond['start'] &&
            $value['end'] <= $beyond['end']) {
            return 'in';
        }

        /*
         * 第一个匹配的标签在第二个外面
         * 条件：第一个开始字节位置 <= 第二个开始位置
         */

        /*
         * ======= start =======
         *
         * {if}
         * value
         *
         * {for}
         * beyond
         * {/for}
         *
         * {/if}
         *
         * ======== end =======
         */
        if ($value['start'] <= $beyond['start'] &&
            $value['end'] >= $beyond['end']) {
            return 'out';
        }

        // 交叉（两个时间段相互关系）
        throw new InvalidArgumentException(
            'Template engine tag library does not support cross.'
        );
    }
protected function positionRelative(array $value, array $beyond): string
    {
        /*
         * 第一个匹配的标签在第二个前面
         * 条件：第一个结束字节位置 <= 第二个开始位置
         */

        /*
         * ======= start =======
         *
         * {if}
         * value
         * {/if}
         *
         * {for}
         * beyond
         * {/for}
         *
         * ======== end =======
         */
        if ($value['end'] <= $beyond['start']) {
            return 'front';
        }

        /*
         * 第一个匹配的标签在第二个后面
         * 条件：第一个开始字节位置 >= 第二个结束位置
         */

        /*
         * ======= start =======
         *
         * {for}
         * beyond
         * {/for}
         *
         * {if}
         * value
         * {/if}
         *
         * ======== end =======
         */
        if ($value['start'] >= $beyond['end']) {
            return 'behind';
        }

        /*
         * 第一个匹配的标签在第二个里面
         * 条件：第一个开始字节位置 >= 第二个开始位置
         */

        /*
         * ======= start =======
         *
         * {for}
         * beyond
         *
         * {if}
         * value
         * {/if}
         *
         * {/for}
         *
         * ======== end =======
         */
        if ($value['start'] >= $beyond['start'] &&
            $value['end'] <= $beyond['end']) {
            return 'in';
        }

        /*
         * 第一个匹配的标签在第二个外面
         * 条件：第一个开始字节位置 <= 第二个开始位置
         */

        /*
         * ======= start =======
         *
         * {if}
         * value
         *
         * {for}
         * beyond
         * {/for}
         *
         * {/if}
         *
         * ======== end =======
         */
        if ($value['start'] <= $beyond['start'] &&
            $value['end'] >= $beyond['end']) {
            return 'out';
        }

        // 交叉（两个时间段相互关系）
        throw new InvalidArgumentException(
            'Template engine tag library does not support cross.'
        );
    }
对比两个模板相对位置
这个和两个时间段之间的关系一样，其中交叉在模板引擎中是不被支持，因为无法实现
除掉交叉，剩下包含、被包含、前面和后面，通过位置组装成一颗树结构.

@param array $value
@param array $beyond

@return string
@note string front 第一个在第二个前面
@note string behind 第一个在第二个后面
@note string in 第一个在第二里面，成为它的子模板
@note string out 第一个在第一个里面，成为它的子模板