using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Runtime.InteropServices; using miew.Debugging; namespace agree { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public interface IMotherDaughter { TfsSection[] RuleDaughters { get; } int KeyDaughterIndex { get; } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Caches rule daughters and arity /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public partial class MotherDaughterTfs : ArrayTfs, IMotherDaughter { public MotherDaughterTfs(Allocator ctrl, TargetTfs tt, int[] rg_feat_delete) : base(ctrl, tt, rg_feat_delete) { } unsafe public MotherDaughterTfs(Allocator ctrl, Edge e_top, arr_tfs_entry* _p_ate, int c, int next_mark, int next_coref_mark, int min_coref_in_mark, bool f_restricted) : base(ctrl, e_top, _p_ate, c, next_mark, next_coref_mark, min_coref_in_mark, f_restricted) { } unsafe public MotherDaughterTfs(Allocator ctrl, Edge e_top, arr_tfs_entry[] rg_ate, ushort[] hidx, ushort[] rgn, int next_mark, int next_coref_mark, bool f_restricted) : base(ctrl, e_top, rg_ate, hidx, rgn, next_mark, next_coref_mark, f_restricted) { } TfsSection[] daughters = null; int i_key_daughter = 0; [DebuggerBrowsable(DebuggerBrowsableState.Never)] public int KeyDaughterIndex { get { if (daughters == null) _lazy_load_rule_daughters(); return i_key_daughter; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] public TfsSection[] RuleDaughters { get { return daughters ?? _lazy_load_rule_daughters(); } } public TfsSection[] _lazy_load_rule_daughters() { #if false /// locate the daughter entry points in the expanded contents TfsSection[] _tmp = GetSectionsFromPathToList(tm.config.RuleArgsPath).ToArray(); #else /// locate the daughter entry points in the expanded contents var rg_lp_edges = tm.config.parser.RuleArgsPath.GetListPathEdges(this).ToArray(); if (rg_lp_edges.Length == 0) throw new Exception(); TfsSection[] _tmp = new TfsSection[rg_lp_edges.Length]; for (int i = 0; i < rg_lp_edges.Length; i++) _tmp[i] = GetSection(rg_lp_edges[i], i); #endif /// find the first KEY daughter, i.e. the first daughter where the type at the KEY daughter path (if /// specified) matches the KEY daughter type (if specified). In the absence of such a match, the /// parser will default to active rightwards expansion starting at daughter index 0. /// As noted in a comment elsewhere, the KEY daughter index remains constant for active edges derived /// from this rule, so we don't need to redo this during parsing; instead we can just copy this value /// over. i_key_daughter = 0; Type t_key = tm.tt_key_daughter; if (!t_key.IsTop) { for (int i = 0; i < _tmp.Length; i++) if (tm.config.parser.KeyDaughterPath.GetType(_tmp[i]) == t_key) { i_key_daughter = i; /// If multiple daughters have KEY-ARG marked, it is not clear what to do. This /// implementation currently elects to take the leftmost acceptable KEY: break; } } return daughters = _tmp; } }; }