diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build-linux.yml index 61d8af4d..34f4c2ca 100644 --- a/.github/workflows/build-linux.yml +++ b/.github/workflows/build-linux.yml @@ -593,6 +593,50 @@ jobs: fi echo "[json] jsonwrite serializes and jsonparse round-trips" + - name: callanalyzer runs another analyzer, loaded once + if: matrix.id != 'docker-ubuntu-20.04' + shell: bash + run: | + set -eo pipefail + # callanalyzer (4.1.0) runs another analyzer's passes on one node of + # this analyzer's parse tree, with this analyzer's KB. The callee + # sits beside the caller, in tests/call-analyzer-callee, and is found + # by name. The tree lines prove it changed only the nodes it was + # given; crimson proves its lazy *full.dict was run on the passed + # text; the load count proves it was built once for two calls. + FIX=.github/workflows/tests/call-analyzer + rm -rf "$FIX/logs" "$FIX/input/text.txt_log" .github/workflows/tests/call-analyzer-callee/logs + mkdir -p "$FIX/logs" + ./bin/nlp -ANA "$FIX" -WORK ./ "$FIX/input/text.txt" 2>&1 | tee "$FIX/logs/run.log" + if [ -f "$FIX/logs/make_ana.log" ]; then cat "$FIX/logs/make_ana.log"; fi + OUT="$FIX/input/text.txt_log/out.txt" + if [ ! -f "$OUT" ]; then + echo "FAIL(callanalyzer): no out.txt -- the analyzer did not build"; exit 1 + fi + got=$(tr -d '\r' < "$OUT") + want=$(printf '%s\n' \ + 'loaded-before:0' \ + 'call:1' \ + 'call:1' \ + 'loaded-after:1' \ + 'mine:caller' \ + 'tree:_sent _color apples* .' \ + 'tree:_sent _color sky* and* _color grass* .' \ + 'tree:Blue' \ + 'concept:sent root:_sent sawcallerG:0 backcall:0 colors:red;' \ + 'concept:sent root:_sent sawcallerG:0 backcall:0 colors:crimson;green;' \ + 'self:0' \ + 'missing:0') + if [ "$got" != "$want" ]; then + echo "FAIL(callanalyzer): out.txt was:"; echo "$got" + echo "wanted:"; echo "$want"; exit 1 + fi + loads=$(grep -c 'callanalyzer: loaded call-analyzer-callee' "$FIX/logs/run.log" || true) + if [ "$loads" != "1" ]; then + echo "FAIL(callanalyzer): the called analyzer was loaded $loads times for two calls"; exit 1 + fi + echo "[callanalyzer] called analyzer ran on the given nodes, loaded once" + - name: Rule-level debug server (Non-20.04) if: matrix.id != 'docker-ubuntu-20.04' shell: bash diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 2b0177e0..fa26fce5 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -522,6 +522,49 @@ jobs: fi echo "[json] jsonwrite serializes and jsonparse round-trips" + - name: callanalyzer runs another analyzer, loaded once + shell: bash + run: | + set -eo pipefail + # callanalyzer (4.1.0) runs another analyzer's passes on one node of + # this analyzer's parse tree, with this analyzer's KB. The callee + # sits beside the caller, in tests/call-analyzer-callee, and is found + # by name. The tree lines prove it changed only the nodes it was + # given; crimson proves its lazy *full.dict was run on the passed + # text; the load count proves it was built once for two calls. + FIX=.github/workflows/tests/call-analyzer + rm -rf "$FIX/logs" "$FIX/input/text.txt_log" .github/workflows/tests/call-analyzer-callee/logs + mkdir -p "$FIX/logs" + ./bin/Release/nlp.exe -ANA "$FIX" -WORK ./ "$FIX/input/text.txt" 2>&1 | tee "$FIX/logs/run.log" + if [ -f "$FIX/logs/make_ana.log" ]; then cat "$FIX/logs/make_ana.log"; fi + OUT="$FIX/input/text.txt_log/out.txt" + if [ ! -f "$OUT" ]; then + echo "FAIL(callanalyzer): no out.txt -- the analyzer did not build"; exit 1 + fi + got=$(tr -d '\r' < "$OUT") + want=$(printf '%s\n' \ + 'loaded-before:0' \ + 'call:1' \ + 'call:1' \ + 'loaded-after:1' \ + 'mine:caller' \ + 'tree:_sent _color apples* .' \ + 'tree:_sent _color sky* and* _color grass* .' \ + 'tree:Blue' \ + 'concept:sent root:_sent sawcallerG:0 backcall:0 colors:red;' \ + 'concept:sent root:_sent sawcallerG:0 backcall:0 colors:crimson;green;' \ + 'self:0' \ + 'missing:0') + if [ "$got" != "$want" ]; then + echo "FAIL(callanalyzer): out.txt was:"; echo "$got" + echo "wanted:"; echo "$want"; exit 1 + fi + loads=$(grep -c 'callanalyzer: loaded call-analyzer-callee' "$FIX/logs/run.log" || true) + if [ "$loads" != "1" ]; then + echo "FAIL(callanalyzer): the called analyzer was loaded $loads times for two calls"; exit 1 + fi + echo "[callanalyzer] called analyzer ran on the given nodes, loaded once" + - name: Rule-level debug server shell: bash run: | diff --git a/.github/workflows/tests/call-analyzer-callee/kb/user/colors.dict b/.github/workflows/tests/call-analyzer-callee/kb/user/colors.dict new file mode 100644 index 00000000..86f7af49 --- /dev/null +++ b/.github/workflows/tests/call-analyzer-callee/kb/user/colors.dict @@ -0,0 +1,3 @@ +blue color=yes +green color=yes +red color=yes diff --git a/.github/workflows/tests/call-analyzer-callee/kb/user/hier.kb b/.github/workflows/tests/call-analyzer-callee/kb/user/hier.kb new file mode 100644 index 00000000..9d513bf1 --- /dev/null +++ b/.github/workflows/tests/call-analyzer-callee/kb/user/hier.kb @@ -0,0 +1,756 @@ +add empty +add root +add hier "concept" "gram" +add hier "concept" "sys" +add hier "concept" "sys" "attrs" +add hier "concept" "sys" "attrs" "proxy" +add hier "concept" "sys" "attrs" "proxy" "atom" +add hier "concept" "sys" "attrs" "pproxy" +add hier "concept" "sys" "attrs" "pproxy" "phrase" +add hier "concept" "sys" "attrs" "common" +add hier "concept" "sys" "attrs" "common" "var" +add hier "concept" "sys" "attrs" "rule_elt" +add hier "concept" "sys" "vals" +add hier "concept" "sys" "vals" "boolean" +add hier "concept" "sys" "vals" "boolean" "false" +add hier "concept" "sys" "vals" "boolean" "true" +add hier "concept" "sys" "nlp" +add hier "concept" "sys" "nlp" "wht" +add hier "concept" "sys" "nlp" "punct" +add hier "concept" "sys" "nlp" "ctrl" +add hier "concept" "sys" "nlp" "lex" +add hier "concept" "sys" "nlp" "lex" "slot" +add hier "concept" "sys" "nlp" "lex" "slot" "cases" +add hier "concept" "sys" "mean" +add hier "concept" "sys" "mean" "slot" +add hier "concept" "sys" "mean" "slot" "case" +add hier "concept" "sys" "mean" "slot" "case" "cap" +add hier "concept" "sys" "mean" "slot" "case" "allcap" +add hier "concept" "sys" "mean" "slot" "case" "mixed" +add hier "concept" "sys" "mean" "slot" "mixed" +add hier "concept" "sys" "dict" +add hier "concept" "sys" "dict" "a" +add hier "concept" "sys" "dict" "a" "A" +add hier "concept" "sys" "dict" "a" "A" "A" +add hier "concept" "sys" "dict" "a" "A" "Aa" +add hier "concept" "sys" "dict" "a" "A" "Ab" +add hier "concept" "sys" "dict" "a" "A" "Ac" +add hier "concept" "sys" "dict" "a" "A" "Ad" +add hier "concept" "sys" "dict" "a" "A" "Ae" +add hier "concept" "sys" "dict" "a" "A" "Af" +add hier "concept" "sys" "dict" "a" "A" "Ag" +add hier "concept" "sys" "dict" "a" "A" "Ah" +add hier "concept" "sys" "dict" "a" "A" "Ai" +add hier "concept" "sys" "dict" "a" "A" "Aj" +add hier "concept" "sys" "dict" "a" "A" "Ak" +add hier "concept" "sys" "dict" "a" "A" "Al" +add hier "concept" "sys" "dict" "a" "A" "Am" +add hier "concept" "sys" "dict" "a" "A" "An" +add hier "concept" "sys" "dict" "a" "A" "Ap" +add hier "concept" "sys" "dict" "a" "A" "Aq" +add hier "concept" "sys" "dict" "a" "A" "Ar" +add hier "concept" "sys" "dict" "a" "A" "As" +add hier "concept" "sys" "dict" "a" "A" "At" +add hier "concept" "sys" "dict" "a" "A" "Au" +add hier "concept" "sys" "dict" "a" "A" "Av" +add hier "concept" "sys" "dict" "a" "A" "Aw" +add hier "concept" "sys" "dict" "a" "A" "Ax" +add hier "concept" "sys" "dict" "a" "A" "Ay" +add hier "concept" "sys" "dict" "a" "A" "Az" +add hier "concept" "sys" "dict" "a" "B" +add hier "concept" "sys" "dict" "a" "B" "B" +add hier "concept" "sys" "dict" "a" "B" "Ba" +add hier "concept" "sys" "dict" "a" "B" "Be" +add hier "concept" "sys" "dict" "a" "B" "Bi" +add hier "concept" "sys" "dict" "a" "B" "Bl" +add hier "concept" "sys" "dict" "a" "B" "Bo" +add hier "concept" "sys" "dict" "a" "B" "Br" +add hier "concept" "sys" "dict" "a" "B" "Bu" +add hier "concept" "sys" "dict" "a" "B" "By" +add hier "concept" "sys" "dict" "a" "C" +add hier "concept" "sys" "dict" "a" "C" "C" +add hier "concept" "sys" "dict" "a" "C" "Ca" +add hier "concept" "sys" "dict" "a" "C" "Ce" +add hier "concept" "sys" "dict" "a" "C" "Ch" +add hier "concept" "sys" "dict" "a" "C" "Ci" +add hier "concept" "sys" "dict" "a" "C" "Cl" +add hier "concept" "sys" "dict" "a" "C" "Co" +add hier "concept" "sys" "dict" "a" "C" "Cr" +add hier "concept" "sys" "dict" "a" "C" "Cu" +add hier "concept" "sys" "dict" "a" "C" "Cy" +add hier "concept" "sys" "dict" "a" "D" +add hier "concept" "sys" "dict" "a" "D" "D" +add hier "concept" "sys" "dict" "a" "D" "Da" +add hier "concept" "sys" "dict" "a" "D" "De" +add hier "concept" "sys" "dict" "a" "D" "Di" +add hier "concept" "sys" "dict" "a" "D" "Do" +add hier "concept" "sys" "dict" "a" "D" "Dr" +add hier "concept" "sys" "dict" "a" "D" "Du" +add hier "concept" "sys" "dict" "a" "D" "Dy" +add hier "concept" "sys" "dict" "a" "E" +add hier "concept" "sys" "dict" "a" "E" "E" +add hier "concept" "sys" "dict" "a" "E" "Ea" +add hier "concept" "sys" "dict" "a" "E" "Eb" +add hier "concept" "sys" "dict" "a" "E" "Ed" +add hier "concept" "sys" "dict" "a" "E" "Ee" +add hier "concept" "sys" "dict" "a" "E" "Ef" +add hier "concept" "sys" "dict" "a" "E" "Eg" +add hier "concept" "sys" "dict" "a" "E" "Eh" +add hier "concept" "sys" "dict" "a" "E" "Ei" +add hier "concept" "sys" "dict" "a" "E" "Ej" +add hier "concept" "sys" "dict" "a" "E" "El" +add hier "concept" "sys" "dict" "a" "E" "Em" +add hier "concept" "sys" "dict" "a" "E" "En" +add hier "concept" "sys" "dict" "a" "E" "Eo" +add hier "concept" "sys" "dict" "a" "E" "Ep" +add hier "concept" "sys" "dict" "a" "E" "Eq" +add hier "concept" "sys" "dict" "a" "E" "Er" +add hier "concept" "sys" "dict" "a" "E" "Es" +add hier "concept" "sys" "dict" "a" "E" "Et" +add hier "concept" "sys" "dict" "a" "E" "Eu" +add hier "concept" "sys" "dict" "a" "E" "Ev" +add hier "concept" "sys" "dict" "a" "E" "Ew" +add hier "concept" "sys" "dict" "a" "E" "Ex" +add hier "concept" "sys" "dict" "a" "E" "Ey" +add hier "concept" "sys" "dict" "a" "E" "Ez" +add hier "concept" "sys" "dict" "a" "F" +add hier "concept" "sys" "dict" "a" "F" "F" +add hier "concept" "sys" "dict" "a" "F" "Fa" +add hier "concept" "sys" "dict" "a" "F" "Fe" +add hier "concept" "sys" "dict" "a" "F" "Fi" +add hier "concept" "sys" "dict" "a" "F" "Fl" +add hier "concept" "sys" "dict" "a" "F" "Fo" +add hier "concept" "sys" "dict" "a" "F" "Fr" +add hier "concept" "sys" "dict" "a" "F" "Fu" +add hier "concept" "sys" "dict" "a" "F" "Fy" +add hier "concept" "sys" "dict" "a" "G" +add hier "concept" "sys" "dict" "a" "G" "G" +add hier "concept" "sys" "dict" "a" "G" "Ga" +add hier "concept" "sys" "dict" "a" "G" "Ge" +add hier "concept" "sys" "dict" "a" "G" "Gh" +add hier "concept" "sys" "dict" "a" "G" "Gi" +add hier "concept" "sys" "dict" "a" "G" "Gl" +add hier "concept" "sys" "dict" "a" "G" "Gn" +add hier "concept" "sys" "dict" "a" "G" "Go" +add hier "concept" "sys" "dict" "a" "G" "Gr" +add hier "concept" "sys" "dict" "a" "G" "Gu" +add hier "concept" "sys" "dict" "a" "G" "Gy" +add hier "concept" "sys" "dict" "a" "H" +add hier "concept" "sys" "dict" "a" "H" "H" +add hier "concept" "sys" "dict" "a" "H" "Ha" +add hier "concept" "sys" "dict" "a" "H" "He" +add hier "concept" "sys" "dict" "a" "H" "Hi" +add hier "concept" "sys" "dict" "a" "H" "Ho" +add hier "concept" "sys" "dict" "a" "H" "Hu" +add hier "concept" "sys" "dict" "a" "H" "Hy" +add hier "concept" "sys" "dict" "a" "I" +add hier "concept" "sys" "dict" "a" "I" "I" +add hier "concept" "sys" "dict" "a" "I" "Ia" +add hier "concept" "sys" "dict" "a" "I" "Ib" +add hier "concept" "sys" "dict" "a" "I" "Ic" +add hier "concept" "sys" "dict" "a" "I" "Id" +add hier "concept" "sys" "dict" "a" "I" "Ig" +add hier "concept" "sys" "dict" "a" "I" "Il" +add hier "concept" "sys" "dict" "a" "I" "Im" +add hier "concept" "sys" "dict" "a" "I" "In" +add hier "concept" "sys" "dict" "a" "I" "Io" +add hier "concept" "sys" "dict" "a" "I" "Ir" +add hier "concept" "sys" "dict" "a" "I" "Is" +add hier "concept" "sys" "dict" "a" "I" "It" +add hier "concept" "sys" "dict" "a" "J" +add hier "concept" "sys" "dict" "a" "J" "J" +add hier "concept" "sys" "dict" "a" "J" "Ja" +add hier "concept" "sys" "dict" "a" "J" "Je" +add hier "concept" "sys" "dict" "a" "J" "Ji" +add hier "concept" "sys" "dict" "a" "J" "Jo" +add hier "concept" "sys" "dict" "a" "J" "Ju" +add hier "concept" "sys" "dict" "a" "K" +add hier "concept" "sys" "dict" "a" "K" "K" +add hier "concept" "sys" "dict" "a" "K" "Ka" +add hier "concept" "sys" "dict" "a" "K" "Ke" +add hier "concept" "sys" "dict" "a" "K" "Kh" +add hier "concept" "sys" "dict" "a" "K" "Ki" +add hier "concept" "sys" "dict" "a" "K" "Kl" +add hier "concept" "sys" "dict" "a" "K" "Kn" +add hier "concept" "sys" "dict" "a" "K" "Ko" +add hier "concept" "sys" "dict" "a" "K" "Kr" +add hier "concept" "sys" "dict" "a" "K" "Ku" +add hier "concept" "sys" "dict" "a" "L" +add hier "concept" "sys" "dict" "a" "L" "L" +add hier "concept" "sys" "dict" "a" "L" "La" +add hier "concept" "sys" "dict" "a" "L" "Le" +add hier "concept" "sys" "dict" "a" "L" "Li" +add hier "concept" "sys" "dict" "a" "L" "Ll" +add hier "concept" "sys" "dict" "a" "L" "Lo" +add hier "concept" "sys" "dict" "a" "L" "Lu" +add hier "concept" "sys" "dict" "a" "L" "Ly" +add hier "concept" "sys" "dict" "a" "M" +add hier "concept" "sys" "dict" "a" "M" "M" +add hier "concept" "sys" "dict" "a" "M" "Ma" +add hier "concept" "sys" "dict" "a" "M" "Me" +add hier "concept" "sys" "dict" "a" "M" "Mi" +add hier "concept" "sys" "dict" "a" "M" "Mn" +add hier "concept" "sys" "dict" "a" "M" "Mo" +add hier "concept" "sys" "dict" "a" "M" "Mu" +add hier "concept" "sys" "dict" "a" "M" "My" +add hier "concept" "sys" "dict" "a" "N" +add hier "concept" "sys" "dict" "a" "N" "N" +add hier "concept" "sys" "dict" "a" "N" "Na" +add hier "concept" "sys" "dict" "a" "N" "Ne" +add hier "concept" "sys" "dict" "a" "N" "Ni" +add hier "concept" "sys" "dict" "a" "N" "No" +add hier "concept" "sys" "dict" "a" "N" "Nu" +add hier "concept" "sys" "dict" "a" "N" "Ny" +add hier "concept" "sys" "dict" "a" "O" +add hier "concept" "sys" "dict" "a" "O" "O" +add hier "concept" "sys" "dict" "a" "O" "Oa" +add hier "concept" "sys" "dict" "a" "O" "Ob" +add hier "concept" "sys" "dict" "a" "O" "Oc" +add hier "concept" "sys" "dict" "a" "O" "Od" +add hier "concept" "sys" "dict" "a" "O" "Oe" +add hier "concept" "sys" "dict" "a" "O" "Of" +add hier "concept" "sys" "dict" "a" "O" "Og" +add hier "concept" "sys" "dict" "a" "O" "Oh" +add hier "concept" "sys" "dict" "a" "O" "Oi" +add hier "concept" "sys" "dict" "a" "O" "Ok" +add hier "concept" "sys" "dict" "a" "O" "On" +add hier "concept" "sys" "dict" "a" "O" "Oo" +add hier "concept" "sys" "dict" "a" "O" "Op" +add hier "concept" "sys" "dict" "a" "O" "Oq" +add hier "concept" "sys" "dict" "a" "O" "Or" +add hier "concept" "sys" "dict" "a" "O" "Os" +add hier "concept" "sys" "dict" "a" "O" "Ot" +add hier "concept" "sys" "dict" "a" "O" "Ou" +add hier "concept" "sys" "dict" "a" "O" "Ov" +add hier "concept" "sys" "dict" "a" "O" "Ow" +add hier "concept" "sys" "dict" "a" "O" "Ox" +add hier "concept" "sys" "dict" "a" "O" "Oy" +add hier "concept" "sys" "dict" "a" "O" "Oz" +add hier "concept" "sys" "dict" "a" "P" +add hier "concept" "sys" "dict" "a" "P" "P" +add hier "concept" "sys" "dict" "a" "P" "Pa" +add hier "concept" "sys" "dict" "a" "P" "Pe" +add hier "concept" "sys" "dict" "a" "P" "Ph" +add hier "concept" "sys" "dict" "a" "P" "Pi" +add hier "concept" "sys" "dict" "a" "P" "Pl" +add hier "concept" "sys" "dict" "a" "P" "Pn" +add hier "concept" "sys" "dict" "a" "P" "Po" +add hier "concept" "sys" "dict" "a" "P" "Pr" +add hier "concept" "sys" "dict" "a" "P" "Pt" +add hier "concept" "sys" "dict" "a" "P" "Pu" +add hier "concept" "sys" "dict" "a" "P" "Py" +add hier "concept" "sys" "dict" "a" "Q" +add hier "concept" "sys" "dict" "a" "Q" "Q" +add hier "concept" "sys" "dict" "a" "Q" "Qa" +add hier "concept" "sys" "dict" "a" "Q" "Qu" +add hier "concept" "sys" "dict" "a" "R" +add hier "concept" "sys" "dict" "a" "R" "R" +add hier "concept" "sys" "dict" "a" "R" "Ra" +add hier "concept" "sys" "dict" "a" "R" "Re" +add hier "concept" "sys" "dict" "a" "R" "Rh" +add hier "concept" "sys" "dict" "a" "R" "Ri" +add hier "concept" "sys" "dict" "a" "R" "Ro" +add hier "concept" "sys" "dict" "a" "R" "Ru" +add hier "concept" "sys" "dict" "a" "R" "Ry" +add hier "concept" "sys" "dict" "a" "S" +add hier "concept" "sys" "dict" "a" "S" "S" +add hier "concept" "sys" "dict" "a" "S" "Sa" +add hier "concept" "sys" "dict" "a" "S" "Sc" +add hier "concept" "sys" "dict" "a" "S" "Se" +add hier "concept" "sys" "dict" "a" "S" "Sf" +add hier "concept" "sys" "dict" "a" "S" "Sh" +add hier "concept" "sys" "dict" "a" "S" "Si" +add hier "concept" "sys" "dict" "a" "S" "Sk" +add hier "concept" "sys" "dict" "a" "S" "Sl" +add hier "concept" "sys" "dict" "a" "S" "Sm" +add hier "concept" "sys" "dict" "a" "S" "Sn" +add hier "concept" "sys" "dict" "a" "S" "So" +add hier "concept" "sys" "dict" "a" "S" "Sp" +add hier "concept" "sys" "dict" "a" "S" "Sq" +add hier "concept" "sys" "dict" "a" "S" "St" +add hier "concept" "sys" "dict" "a" "S" "Su" +add hier "concept" "sys" "dict" "a" "S" "Sw" +add hier "concept" "sys" "dict" "a" "S" "Sy" +add hier "concept" "sys" "dict" "a" "T" +add hier "concept" "sys" "dict" "a" "T" "T" +add hier "concept" "sys" "dict" "a" "T" "Ta" +add hier "concept" "sys" "dict" "a" "T" "Te" +add hier "concept" "sys" "dict" "a" "T" "Th" +add hier "concept" "sys" "dict" "a" "T" "Ti" +add hier "concept" "sys" "dict" "a" "T" "To" +add hier "concept" "sys" "dict" "a" "T" "Tr" +add hier "concept" "sys" "dict" "a" "T" "Tu" +add hier "concept" "sys" "dict" "a" "T" "Tw" +add hier "concept" "sys" "dict" "a" "T" "Ty" +add hier "concept" "sys" "dict" "a" "U" +add hier "concept" "sys" "dict" "a" "U" "U" +add hier "concept" "sys" "dict" "a" "U" "Ua" +add hier "concept" "sys" "dict" "a" "U" "Un" +add hier "concept" "sys" "dict" "a" "U" "Up" +add hier "concept" "sys" "dict" "a" "U" "Ur" +add hier "concept" "sys" "dict" "a" "V" +add hier "concept" "sys" "dict" "a" "V" "V" +add hier "concept" "sys" "dict" "a" "V" "Va" +add hier "concept" "sys" "dict" "a" "V" "Ve" +add hier "concept" "sys" "dict" "a" "V" "Vi" +add hier "concept" "sys" "dict" "a" "V" "Vo" +add hier "concept" "sys" "dict" "a" "V" "Vu" +add hier "concept" "sys" "dict" "a" "W" +add hier "concept" "sys" "dict" "a" "W" "W" +add hier "concept" "sys" "dict" "a" "W" "Wa" +add hier "concept" "sys" "dict" "a" "W" "We" +add hier "concept" "sys" "dict" "a" "W" "Wh" +add hier "concept" "sys" "dict" "a" "W" "Wi" +add hier "concept" "sys" "dict" "a" "W" "Wo" +add hier "concept" "sys" "dict" "a" "W" "Wr" +add hier "concept" "sys" "dict" "a" "W" "Wu" +add hier "concept" "sys" "dict" "a" "X" +add hier "concept" "sys" "dict" "a" "X" "X" +add hier "concept" "sys" "dict" "a" "X" "Xa" +add hier "concept" "sys" "dict" "a" "X" "Xe" +add hier "concept" "sys" "dict" "a" "X" "Xi" +add hier "concept" "sys" "dict" "a" "X" "Xo" +add hier "concept" "sys" "dict" "a" "X" "Xu" +add hier "concept" "sys" "dict" "a" "X" "Xy" +add hier "concept" "sys" "dict" "a" "Y" +add hier "concept" "sys" "dict" "a" "Y" "Y" +add hier "concept" "sys" "dict" "a" "Y" "Ya" +add hier "concept" "sys" "dict" "a" "Y" "Ye" +add hier "concept" "sys" "dict" "a" "Y" "Yi" +add hier "concept" "sys" "dict" "a" "Y" "Yo" +add hier "concept" "sys" "dict" "a" "Y" "Yu" +add hier "concept" "sys" "dict" "a" "Z" +add hier "concept" "sys" "dict" "a" "Z" "Z" +add hier "concept" "sys" "dict" "a" "Z" "Za" +add hier "concept" "sys" "dict" "a" "Z" "Ze" +add hier "concept" "sys" "dict" "a" "Z" "Zi" +add hier "concept" "sys" "dict" "a" "Z" "Zo" +add hier "concept" "sys" "dict" "a" "Z" "Zu" +add hier "concept" "sys" "dict" "a" "Z" "Zy" +add hier "concept" "sys" "dict" "a" "a" +add hier "concept" "sys" "dict" "a" "a" "a" +add hier "concept" "sys" "dict" "a" "a" "aa" +add hier "concept" "sys" "dict" "a" "a" "ab" +add hier "concept" "sys" "dict" "a" "a" "ac" +add hier "concept" "sys" "dict" "a" "a" "ad" +add hier "concept" "sys" "dict" "a" "a" "ae" +add hier "concept" "sys" "dict" "a" "a" "af" +add hier "concept" "sys" "dict" "a" "a" "ag" +add hier "concept" "sys" "dict" "a" "a" "ah" +add hier "concept" "sys" "dict" "a" "a" "ai" +add hier "concept" "sys" "dict" "a" "a" "aj" +add hier "concept" "sys" "dict" "a" "a" "ak" +add hier "concept" "sys" "dict" "a" "a" "al" +add hier "concept" "sys" "dict" "a" "a" "am" +add hier "concept" "sys" "dict" "a" "a" "an" +add hier "concept" "sys" "dict" "a" "a" "ap" +add hier "concept" "sys" "dict" "a" "a" "aq" +add hier "concept" "sys" "dict" "a" "a" "ar" +add hier "concept" "sys" "dict" "a" "a" "as" +add hier "concept" "sys" "dict" "a" "a" "at" +add hier "concept" "sys" "dict" "a" "a" "au" +add hier "concept" "sys" "dict" "a" "a" "av" +add hier "concept" "sys" "dict" "a" "a" "aw" +add hier "concept" "sys" "dict" "a" "a" "ax" +add hier "concept" "sys" "dict" "a" "a" "ay" +add hier "concept" "sys" "dict" "a" "a" "az" +add hier "concept" "sys" "dict" "a" "b" +add hier "concept" "sys" "dict" "a" "b" "b" +add hier "concept" "sys" "dict" "a" "b" "ba" +add hier "concept" "sys" "dict" "a" "b" "be" +add hier "concept" "sys" "dict" "a" "b" "bi" +add hier "concept" "sys" "dict" "a" "b" "bl" +add hier "concept" "sys" "dict" "a" "b" "bo" +add hier "concept" "sys" "dict" "a" "b" "br" +add hier "concept" "sys" "dict" "a" "b" "bu" +add hier "concept" "sys" "dict" "a" "b" "by" +add hier "concept" "sys" "dict" "a" "c" +add hier "concept" "sys" "dict" "a" "c" "c" +add hier "concept" "sys" "dict" "a" "c" "ca" +add hier "concept" "sys" "dict" "a" "c" "ce" +add hier "concept" "sys" "dict" "a" "c" "ch" +add hier "concept" "sys" "dict" "a" "c" "ci" +add hier "concept" "sys" "dict" "a" "c" "cl" +add hier "concept" "sys" "dict" "a" "c" "co" +add hier "concept" "sys" "dict" "a" "c" "cr" +add hier "concept" "sys" "dict" "a" "c" "cu" +add hier "concept" "sys" "dict" "a" "c" "cy" +add hier "concept" "sys" "dict" "a" "d" +add hier "concept" "sys" "dict" "a" "d" "d" +add hier "concept" "sys" "dict" "a" "d" "da" +add hier "concept" "sys" "dict" "a" "d" "de" +add hier "concept" "sys" "dict" "a" "d" "di" +add hier "concept" "sys" "dict" "a" "d" "do" +add hier "concept" "sys" "dict" "a" "d" "dr" +add hier "concept" "sys" "dict" "a" "d" "du" +add hier "concept" "sys" "dict" "a" "d" "dy" +add hier "concept" "sys" "dict" "a" "e" +add hier "concept" "sys" "dict" "a" "e" "e" +add hier "concept" "sys" "dict" "a" "e" "ea" +add hier "concept" "sys" "dict" "a" "e" "eb" +add hier "concept" "sys" "dict" "a" "e" "ed" +add hier "concept" "sys" "dict" "a" "e" "ee" +add hier "concept" "sys" "dict" "a" "e" "ef" +add hier "concept" "sys" "dict" "a" "e" "eg" +add hier "concept" "sys" "dict" "a" "e" "eh" +add hier "concept" "sys" "dict" "a" "e" "ei" +add hier "concept" "sys" "dict" "a" "e" "ej" +add hier "concept" "sys" "dict" "a" "e" "el" +add hier "concept" "sys" "dict" "a" "e" "em" +add hier "concept" "sys" "dict" "a" "e" "en" +add hier "concept" "sys" "dict" "a" "e" "eo" +add hier "concept" "sys" "dict" "a" "e" "ep" +add hier "concept" "sys" "dict" "a" "e" "eq" +add hier "concept" "sys" "dict" "a" "e" "er" +add hier "concept" "sys" "dict" "a" "e" "es" +add hier "concept" "sys" "dict" "a" "e" "et" +add hier "concept" "sys" "dict" "a" "e" "eu" +add hier "concept" "sys" "dict" "a" "e" "ev" +add hier "concept" "sys" "dict" "a" "e" "ew" +add hier "concept" "sys" "dict" "a" "e" "ex" +add hier "concept" "sys" "dict" "a" "e" "ey" +add hier "concept" "sys" "dict" "a" "e" "ez" +add hier "concept" "sys" "dict" "a" "f" +add hier "concept" "sys" "dict" "a" "f" "f" +add hier "concept" "sys" "dict" "a" "f" "fa" +add hier "concept" "sys" "dict" "a" "f" "fe" +add hier "concept" "sys" "dict" "a" "f" "fi" +add hier "concept" "sys" "dict" "a" "f" "fl" +add hier "concept" "sys" "dict" "a" "f" "fo" +add hier "concept" "sys" "dict" "a" "f" "fr" +add hier "concept" "sys" "dict" "a" "f" "fu" +add hier "concept" "sys" "dict" "a" "f" "fy" +add hier "concept" "sys" "dict" "a" "g" +add hier "concept" "sys" "dict" "a" "g" "g" +add hier "concept" "sys" "dict" "a" "g" "ga" +add hier "concept" "sys" "dict" "a" "g" "ge" +add hier "concept" "sys" "dict" "a" "g" "gh" +add hier "concept" "sys" "dict" "a" "g" "gi" +add hier "concept" "sys" "dict" "a" "g" "gl" +add hier "concept" "sys" "dict" "a" "g" "gn" +add hier "concept" "sys" "dict" "a" "g" "go" +add hier "concept" "sys" "dict" "a" "g" "gr" +add hier "concept" "sys" "dict" "a" "g" "gu" +add hier "concept" "sys" "dict" "a" "g" "gy" +add hier "concept" "sys" "dict" "a" "h" +add hier "concept" "sys" "dict" "a" "h" "h" +add hier "concept" "sys" "dict" "a" "h" "ha" +add hier "concept" "sys" "dict" "a" "h" "he" +add hier "concept" "sys" "dict" "a" "h" "hi" +add hier "concept" "sys" "dict" "a" "h" "ho" +add hier "concept" "sys" "dict" "a" "h" "hu" +add hier "concept" "sys" "dict" "a" "h" "hy" +add hier "concept" "sys" "dict" "a" "i" +add hier "concept" "sys" "dict" "a" "i" "i" +add hier "concept" "sys" "dict" "a" "i" "ia" +add hier "concept" "sys" "dict" "a" "i" "ib" +add hier "concept" "sys" "dict" "a" "i" "ic" +add hier "concept" "sys" "dict" "a" "i" "id" +add hier "concept" "sys" "dict" "a" "i" "ig" +add hier "concept" "sys" "dict" "a" "i" "il" +add hier "concept" "sys" "dict" "a" "i" "im" +add hier "concept" "sys" "dict" "a" "i" "in" +add hier "concept" "sys" "dict" "a" "i" "io" +add hier "concept" "sys" "dict" "a" "i" "ir" +add hier "concept" "sys" "dict" "a" "i" "is" +add hier "concept" "sys" "dict" "a" "i" "it" +add hier "concept" "sys" "dict" "a" "j" +add hier "concept" "sys" "dict" "a" "j" "j" +add hier "concept" "sys" "dict" "a" "j" "ja" +add hier "concept" "sys" "dict" "a" "j" "je" +add hier "concept" "sys" "dict" "a" "j" "ji" +add hier "concept" "sys" "dict" "a" "j" "jo" +add hier "concept" "sys" "dict" "a" "j" "ju" +add hier "concept" "sys" "dict" "a" "k" +add hier "concept" "sys" "dict" "a" "k" "k" +add hier "concept" "sys" "dict" "a" "k" "ka" +add hier "concept" "sys" "dict" "a" "k" "ke" +add hier "concept" "sys" "dict" "a" "k" "kh" +add hier "concept" "sys" "dict" "a" "k" "ki" +add hier "concept" "sys" "dict" "a" "k" "kl" +add hier "concept" "sys" "dict" "a" "k" "kn" +add hier "concept" "sys" "dict" "a" "k" "ko" +add hier "concept" "sys" "dict" "a" "k" "kr" +add hier "concept" "sys" "dict" "a" "k" "ku" +add hier "concept" "sys" "dict" "a" "l" +add hier "concept" "sys" "dict" "a" "l" "l" +add hier "concept" "sys" "dict" "a" "l" "la" +add hier "concept" "sys" "dict" "a" "l" "le" +add hier "concept" "sys" "dict" "a" "l" "li" +add hier "concept" "sys" "dict" "a" "l" "ll" +add hier "concept" "sys" "dict" "a" "l" "lo" +add hier "concept" "sys" "dict" "a" "l" "lu" +add hier "concept" "sys" "dict" "a" "l" "ly" +add hier "concept" "sys" "dict" "a" "m" +add hier "concept" "sys" "dict" "a" "m" "m" +add hier "concept" "sys" "dict" "a" "m" "ma" +add hier "concept" "sys" "dict" "a" "m" "me" +add hier "concept" "sys" "dict" "a" "m" "mi" +add hier "concept" "sys" "dict" "a" "m" "mn" +add hier "concept" "sys" "dict" "a" "m" "mo" +add hier "concept" "sys" "dict" "a" "m" "mu" +add hier "concept" "sys" "dict" "a" "m" "my" +add hier "concept" "sys" "dict" "a" "n" +add hier "concept" "sys" "dict" "a" "n" "n" +add hier "concept" "sys" "dict" "a" "n" "na" +add hier "concept" "sys" "dict" "a" "n" "ne" +add hier "concept" "sys" "dict" "a" "n" "ni" +add hier "concept" "sys" "dict" "a" "n" "no" +add hier "concept" "sys" "dict" "a" "n" "nu" +add hier "concept" "sys" "dict" "a" "n" "ny" +add hier "concept" "sys" "dict" "a" "o" +add hier "concept" "sys" "dict" "a" "o" "o" +add hier "concept" "sys" "dict" "a" "o" "oa" +add hier "concept" "sys" "dict" "a" "o" "ob" +add hier "concept" "sys" "dict" "a" "o" "oc" +add hier "concept" "sys" "dict" "a" "o" "od" +add hier "concept" "sys" "dict" "a" "o" "oe" +add hier "concept" "sys" "dict" "a" "o" "of" +add hier "concept" "sys" "dict" "a" "o" "og" +add hier "concept" "sys" "dict" "a" "o" "oh" +add hier "concept" "sys" "dict" "a" "o" "oi" +add hier "concept" "sys" "dict" "a" "o" "ok" +add hier "concept" "sys" "dict" "a" "o" "on" +add hier "concept" "sys" "dict" "a" "o" "oo" +add hier "concept" "sys" "dict" "a" "o" "op" +add hier "concept" "sys" "dict" "a" "o" "oq" +add hier "concept" "sys" "dict" "a" "o" "or" +add hier "concept" "sys" "dict" "a" "o" "os" +add hier "concept" "sys" "dict" "a" "o" "ot" +add hier "concept" "sys" "dict" "a" "o" "ou" +add hier "concept" "sys" "dict" "a" "o" "ov" +add hier "concept" "sys" "dict" "a" "o" "ow" +add hier "concept" "sys" "dict" "a" "o" "ox" +add hier "concept" "sys" "dict" "a" "o" "oy" +add hier "concept" "sys" "dict" "a" "o" "oz" +add hier "concept" "sys" "dict" "a" "p" +add hier "concept" "sys" "dict" "a" "p" "p" +add hier "concept" "sys" "dict" "a" "p" "pa" +add hier "concept" "sys" "dict" "a" "p" "pe" +add hier "concept" "sys" "dict" "a" "p" "ph" +add hier "concept" "sys" "dict" "a" "p" "pi" +add hier "concept" "sys" "dict" "a" "p" "pl" +add hier "concept" "sys" "dict" "a" "p" "pn" +add hier "concept" "sys" "dict" "a" "p" "po" +add hier "concept" "sys" "dict" "a" "p" "pr" +add hier "concept" "sys" "dict" "a" "p" "pt" +add hier "concept" "sys" "dict" "a" "p" "pu" +add hier "concept" "sys" "dict" "a" "p" "py" +add hier "concept" "sys" "dict" "a" "q" +add hier "concept" "sys" "dict" "a" "q" "q" +add hier "concept" "sys" "dict" "a" "q" "qa" +add hier "concept" "sys" "dict" "a" "q" "qu" +add hier "concept" "sys" "dict" "a" "r" +add hier "concept" "sys" "dict" "a" "r" "r" +add hier "concept" "sys" "dict" "a" "r" "ra" +add hier "concept" "sys" "dict" "a" "r" "re" +add hier "concept" "sys" "dict" "a" "r" "rh" +add hier "concept" "sys" "dict" "a" "r" "ri" +add hier "concept" "sys" "dict" "a" "r" "ro" +add hier "concept" "sys" "dict" "a" "r" "ru" +add hier "concept" "sys" "dict" "a" "r" "ry" +add hier "concept" "sys" "dict" "a" "s" +add hier "concept" "sys" "dict" "a" "s" "s" +add hier "concept" "sys" "dict" "a" "s" "sa" +add hier "concept" "sys" "dict" "a" "s" "sc" +add hier "concept" "sys" "dict" "a" "s" "se" +add hier "concept" "sys" "dict" "a" "s" "sf" +add hier "concept" "sys" "dict" "a" "s" "sh" +add hier "concept" "sys" "dict" "a" "s" "si" +add hier "concept" "sys" "dict" "a" "s" "sk" +add hier "concept" "sys" "dict" "a" "s" "sl" +add hier "concept" "sys" "dict" "a" "s" "sm" +add hier "concept" "sys" "dict" "a" "s" "sn" +add hier "concept" "sys" "dict" "a" "s" "so" +add hier "concept" "sys" "dict" "a" "s" "sp" +add hier "concept" "sys" "dict" "a" "s" "sq" +add hier "concept" "sys" "dict" "a" "s" "st" +add hier "concept" "sys" "dict" "a" "s" "su" +add hier "concept" "sys" "dict" "a" "s" "sw" +add hier "concept" "sys" "dict" "a" "s" "sy" +add hier "concept" "sys" "dict" "a" "t" +add hier "concept" "sys" "dict" "a" "t" "t" +add hier "concept" "sys" "dict" "a" "t" "ta" +add hier "concept" "sys" "dict" "a" "t" "te" +add hier "concept" "sys" "dict" "a" "t" "th" +add hier "concept" "sys" "dict" "a" "t" "ti" +add hier "concept" "sys" "dict" "a" "t" "to" +add hier "concept" "sys" "dict" "a" "t" "tr" +add hier "concept" "sys" "dict" "a" "t" "tu" +add hier "concept" "sys" "dict" "a" "t" "tw" +add hier "concept" "sys" "dict" "a" "t" "ty" +add hier "concept" "sys" "dict" "a" "u" +add hier "concept" "sys" "dict" "a" "u" "u" +add hier "concept" "sys" "dict" "a" "u" "ua" +add hier "concept" "sys" "dict" "a" "u" "un" +add hier "concept" "sys" "dict" "a" "u" "up" +add hier "concept" "sys" "dict" "a" "u" "ur" +add hier "concept" "sys" "dict" "a" "v" +add hier "concept" "sys" "dict" "a" "v" "v" +add hier "concept" "sys" "dict" "a" "v" "va" +add hier "concept" "sys" "dict" "a" "v" "ve" +add hier "concept" "sys" "dict" "a" "v" "vi" +add hier "concept" "sys" "dict" "a" "v" "vo" +add hier "concept" "sys" "dict" "a" "v" "vu" +add hier "concept" "sys" "dict" "a" "w" +add hier "concept" "sys" "dict" "a" "w" "w" +add hier "concept" "sys" "dict" "a" "w" "wa" +add hier "concept" "sys" "dict" "a" "w" "we" +add hier "concept" "sys" "dict" "a" "w" "wh" +add hier "concept" "sys" "dict" "a" "w" "wi" +add hier "concept" "sys" "dict" "a" "w" "wo" +add hier "concept" "sys" "dict" "a" "w" "wr" +add hier "concept" "sys" "dict" "a" "w" "wu" +add hier "concept" "sys" "dict" "a" "x" +add hier "concept" "sys" "dict" "a" "x" "x" +add hier "concept" "sys" "dict" "a" "x" "xa" +add hier "concept" "sys" "dict" "a" "x" "xe" +add hier "concept" "sys" "dict" "a" "x" "xi" +add hier "concept" "sys" "dict" "a" "x" "xo" +add hier "concept" "sys" "dict" "a" "x" "xu" +add hier "concept" "sys" "dict" "a" "x" "xy" +add hier "concept" "sys" "dict" "a" "y" +add hier "concept" "sys" "dict" "a" "y" "y" +add hier "concept" "sys" "dict" "a" "y" "ya" +add hier "concept" "sys" "dict" "a" "y" "ye" +add hier "concept" "sys" "dict" "a" "y" "yi" +add hier "concept" "sys" "dict" "a" "y" "yo" +add hier "concept" "sys" "dict" "a" "y" "yu" +add hier "concept" "sys" "dict" "a" "z" +add hier "concept" "sys" "dict" "a" "z" "z" +add hier "concept" "sys" "dict" "a" "z" "za" +add hier "concept" "sys" "dict" "a" "z" "ze" +add hier "concept" "sys" "dict" "a" "z" "zi" +add hier "concept" "sys" "dict" "a" "z" "zo" +add hier "concept" "sys" "dict" "a" "z" "zu" +add hier "concept" "sys" "dict" "a" "z" "zy" +add hier "concept" "sys" "dict" "0" +add hier "concept" "sys" "dict" "0" "0" +add hier "concept" "sys" "dict" "0" "0" "0" +add hier "concept" "sys" "dict" "0" "0" "00" +add hier "concept" "sys" "dict" "0" "0" "01" +add hier "concept" "sys" "dict" "0" "0" "02" +add hier "concept" "sys" "dict" "0" "0" "03" +add hier "concept" "sys" "dict" "0" "0" "04" +add hier "concept" "sys" "dict" "0" "0" "05" +add hier "concept" "sys" "dict" "0" "0" "06" +add hier "concept" "sys" "dict" "0" "0" "07" +add hier "concept" "sys" "dict" "0" "0" "08" +add hier "concept" "sys" "dict" "0" "0" "09" +add hier "concept" "sys" "dict" "0" "1" +add hier "concept" "sys" "dict" "0" "1" "1" +add hier "concept" "sys" "dict" "0" "1" "10" +add hier "concept" "sys" "dict" "0" "1" "11" +add hier "concept" "sys" "dict" "0" "1" "12" +add hier "concept" "sys" "dict" "0" "1" "13" +add hier "concept" "sys" "dict" "0" "1" "14" +add hier "concept" "sys" "dict" "0" "1" "15" +add hier "concept" "sys" "dict" "0" "1" "16" +add hier "concept" "sys" "dict" "0" "1" "17" +add hier "concept" "sys" "dict" "0" "1" "18" +add hier "concept" "sys" "dict" "0" "1" "19" +add hier "concept" "sys" "dict" "0" "2" +add hier "concept" "sys" "dict" "0" "2" "2" +add hier "concept" "sys" "dict" "0" "2" "20" +add hier "concept" "sys" "dict" "0" "2" "21" +add hier "concept" "sys" "dict" "0" "2" "22" +add hier "concept" "sys" "dict" "0" "2" "23" +add hier "concept" "sys" "dict" "0" "2" "24" +add hier "concept" "sys" "dict" "0" "2" "25" +add hier "concept" "sys" "dict" "0" "2" "26" +add hier "concept" "sys" "dict" "0" "2" "27" +add hier "concept" "sys" "dict" "0" "2" "28" +add hier "concept" "sys" "dict" "0" "2" "29" +add hier "concept" "sys" "dict" "0" "3" +add hier "concept" "sys" "dict" "0" "3" "3" +add hier "concept" "sys" "dict" "0" "3" "30" +add hier "concept" "sys" "dict" "0" "3" "31" +add hier "concept" "sys" "dict" "0" "3" "32" +add hier "concept" "sys" "dict" "0" "3" "33" +add hier "concept" "sys" "dict" "0" "3" "34" +add hier "concept" "sys" "dict" "0" "3" "35" +add hier "concept" "sys" "dict" "0" "3" "36" +add hier "concept" "sys" "dict" "0" "3" "37" +add hier "concept" "sys" "dict" "0" "3" "38" +add hier "concept" "sys" "dict" "0" "3" "39" +add hier "concept" "sys" "dict" "0" "4" +add hier "concept" "sys" "dict" "0" "4" "4" +add hier "concept" "sys" "dict" "0" "4" "40" +add hier "concept" "sys" "dict" "0" "4" "41" +add hier "concept" "sys" "dict" "0" "4" "42" +add hier "concept" "sys" "dict" "0" "4" "43" +add hier "concept" "sys" "dict" "0" "4" "44" +add hier "concept" "sys" "dict" "0" "4" "45" +add hier "concept" "sys" "dict" "0" "4" "46" +add hier "concept" "sys" "dict" "0" "4" "47" +add hier "concept" "sys" "dict" "0" "4" "48" +add hier "concept" "sys" "dict" "0" "4" "49" +add hier "concept" "sys" "dict" "0" "5" +add hier "concept" "sys" "dict" "0" "5" "5" +add hier "concept" "sys" "dict" "0" "5" "50" +add hier "concept" "sys" "dict" "0" "5" "51" +add hier "concept" "sys" "dict" "0" "5" "52" +add hier "concept" "sys" "dict" "0" "5" "53" +add hier "concept" "sys" "dict" "0" "5" "54" +add hier "concept" "sys" "dict" "0" "5" "55" +add hier "concept" "sys" "dict" "0" "5" "56" +add hier "concept" "sys" "dict" "0" "5" "57" +add hier "concept" "sys" "dict" "0" "5" "58" +add hier "concept" "sys" "dict" "0" "5" "59" +add hier "concept" "sys" "dict" "0" "6" +add hier "concept" "sys" "dict" "0" "6" "6" +add hier "concept" "sys" "dict" "0" "6" "60" +add hier "concept" "sys" "dict" "0" "6" "61" +add hier "concept" "sys" "dict" "0" "6" "62" +add hier "concept" "sys" "dict" "0" "6" "63" +add hier "concept" "sys" "dict" "0" "6" "64" +add hier "concept" "sys" "dict" "0" "6" "65" +add hier "concept" "sys" "dict" "0" "6" "66" +add hier "concept" "sys" "dict" "0" "6" "67" +add hier "concept" "sys" "dict" "0" "6" "68" +add hier "concept" "sys" "dict" "0" "6" "69" +add hier "concept" "sys" "dict" "0" "7" +add hier "concept" "sys" "dict" "0" "7" "7" +add hier "concept" "sys" "dict" "0" "7" "70" +add hier "concept" "sys" "dict" "0" "7" "71" +add hier "concept" "sys" "dict" "0" "7" "72" +add hier "concept" "sys" "dict" "0" "7" "73" +add hier "concept" "sys" "dict" "0" "7" "74" +add hier "concept" "sys" "dict" "0" "7" "75" +add hier "concept" "sys" "dict" "0" "7" "76" +add hier "concept" "sys" "dict" "0" "7" "77" +add hier "concept" "sys" "dict" "0" "7" "78" +add hier "concept" "sys" "dict" "0" "7" "79" +add hier "concept" "sys" "dict" "0" "8" +add hier "concept" "sys" "dict" "0" "8" "8" +add hier "concept" "sys" "dict" "0" "8" "80" +add hier "concept" "sys" "dict" "0" "8" "81" +add hier "concept" "sys" "dict" "0" "8" "82" +add hier "concept" "sys" "dict" "0" "8" "83" +add hier "concept" "sys" "dict" "0" "8" "84" +add hier "concept" "sys" "dict" "0" "8" "85" +add hier "concept" "sys" "dict" "0" "8" "86" +add hier "concept" "sys" "dict" "0" "8" "87" +add hier "concept" "sys" "dict" "0" "8" "88" +add hier "concept" "sys" "dict" "0" "8" "89" +add hier "concept" "sys" "dict" "0" "9" +add hier "concept" "sys" "dict" "0" "9" "9" +add hier "concept" "sys" "dict" "0" "9" "90" +add hier "concept" "sys" "dict" "0" "9" "91" +add hier "concept" "sys" "dict" "0" "9" "92" +add hier "concept" "sys" "dict" "0" "9" "93" +add hier "concept" "sys" "dict" "0" "9" "94" +add hier "concept" "sys" "dict" "0" "9" "95" +add hier "concept" "sys" "dict" "0" "9" "96" +add hier "concept" "sys" "dict" "0" "9" "97" +add hier "concept" "sys" "dict" "0" "9" "98" +add hier "concept" "sys" "dict" "0" "9" "99" +add hier "concept" "sys" "dict" "A" +add hier "concept" "sys" "dict" "wht" +add hier "concept" "sys" "dict" "pnct" +add hier "concept" "sys" "dict" "ctrl" +add hier "concept" "sys" "dict" "emoji" +add hier "concept" "sys" "dict" "unknown" + +quit + diff --git a/.github/workflows/tests/call-analyzer-callee/kb/user/shades-full.dict b/.github/workflows/tests/call-analyzer-callee/kb/user/shades-full.dict new file mode 100644 index 00000000..da6a951f --- /dev/null +++ b/.github/workflows/tests/call-analyzer-callee/kb/user/shades-full.dict @@ -0,0 +1,2 @@ +crimson color=yes +scarlet color=yes diff --git a/.github/workflows/tests/call-analyzer-callee/spec/analyzer.seq b/.github/workflows/tests/call-analyzer-callee/spec/analyzer.seq new file mode 100644 index 00000000..93f027a7 --- /dev/null +++ b/.github/workflows/tests/call-analyzer-callee/spec/analyzer.seq @@ -0,0 +1,3 @@ +dicttok nil # when called: look up the given node's words, lazy files included +nlp colors # turn color words into _color nodes and record them +nlp mark # mark every other word it was given diff --git a/.github/workflows/tests/call-analyzer-callee/spec/colors.nlp b/.github/workflows/tests/call-analyzer-callee/spec/colors.nlp new file mode 100644 index 00000000..a48595f2 --- /dev/null +++ b/.github/workflows/tests/call-analyzer-callee/spec/colors.nlp @@ -0,0 +1,32 @@ +############################################### +# FILE: colors.nlp +# SUBJ: The analyzer tests/call-analyzer calls. Works on the node it is +# given and records the colors it finds in callconcept(). +# NOTE: Not run on its own by CI. +############################################### + +@CODE +L("out") = callconcept(); +addstrval(L("out"),"root",pnname(pnroot())); + +# The caller's G() variables are not visible here. +if (G("mine")) + addnumval(L("out"),"sawcallerG",1); +else + addnumval(L("out"),"sawcallerG",0); +G("mine") = "callee"; + +# The analyzer that called this one is still running, so this is refused. +addnumval(L("out"),"backcall",callanalyzer(pnroot(),L("out"),"call-analyzer")); +@@CODE + +@CHECK +if (!N("color",1)) + fail(); + +@POST +addstrval(callconcept(),"color",strtolower(N("$text",1))); +single(); + +@RULES +_color <- _xALPHA @@ diff --git a/.github/workflows/tests/call-analyzer-callee/spec/mark.nlp b/.github/workflows/tests/call-analyzer-callee/spec/mark.nlp new file mode 100644 index 00000000..18d3079c --- /dev/null +++ b/.github/workflows/tests/call-analyzer-callee/spec/mark.nlp @@ -0,0 +1,11 @@ +############################################### +# FILE: mark.nlp +# SUBJ: Mark every word left, so the caller can see which nodes this +# analyzer reached. +############################################### + +@POST +N("callee",1) = 1; + +@RULES +_xNIL <- _xALPHA @@ diff --git a/.github/workflows/tests/call-analyzer/input/text.txt b/.github/workflows/tests/call-analyzer/input/text.txt new file mode 100644 index 00000000..7ac21f14 --- /dev/null +++ b/.github/workflows/tests/call-analyzer/input/text.txt @@ -0,0 +1 @@ +Red apples. Crimson sky and green grass. Blue diff --git a/.github/workflows/tests/call-analyzer/kb/user/hier.kb b/.github/workflows/tests/call-analyzer/kb/user/hier.kb new file mode 100644 index 00000000..9d513bf1 --- /dev/null +++ b/.github/workflows/tests/call-analyzer/kb/user/hier.kb @@ -0,0 +1,756 @@ +add empty +add root +add hier "concept" "gram" +add hier "concept" "sys" +add hier "concept" "sys" "attrs" +add hier "concept" "sys" "attrs" "proxy" +add hier "concept" "sys" "attrs" "proxy" "atom" +add hier "concept" "sys" "attrs" "pproxy" +add hier "concept" "sys" "attrs" "pproxy" "phrase" +add hier "concept" "sys" "attrs" "common" +add hier "concept" "sys" "attrs" "common" "var" +add hier "concept" "sys" "attrs" "rule_elt" +add hier "concept" "sys" "vals" +add hier "concept" "sys" "vals" "boolean" +add hier "concept" "sys" "vals" "boolean" "false" +add hier "concept" "sys" "vals" "boolean" "true" +add hier "concept" "sys" "nlp" +add hier "concept" "sys" "nlp" "wht" +add hier "concept" "sys" "nlp" "punct" +add hier "concept" "sys" "nlp" "ctrl" +add hier "concept" "sys" "nlp" "lex" +add hier "concept" "sys" "nlp" "lex" "slot" +add hier "concept" "sys" "nlp" "lex" "slot" "cases" +add hier "concept" "sys" "mean" +add hier "concept" "sys" "mean" "slot" +add hier "concept" "sys" "mean" "slot" "case" +add hier "concept" "sys" "mean" "slot" "case" "cap" +add hier "concept" "sys" "mean" "slot" "case" "allcap" +add hier "concept" "sys" "mean" "slot" "case" "mixed" +add hier "concept" "sys" "mean" "slot" "mixed" +add hier "concept" "sys" "dict" +add hier "concept" "sys" "dict" "a" +add hier "concept" "sys" "dict" "a" "A" +add hier "concept" "sys" "dict" "a" "A" "A" +add hier "concept" "sys" "dict" "a" "A" "Aa" +add hier "concept" "sys" "dict" "a" "A" "Ab" +add hier "concept" "sys" "dict" "a" "A" "Ac" +add hier "concept" "sys" "dict" "a" "A" "Ad" +add hier "concept" "sys" "dict" "a" "A" "Ae" +add hier "concept" "sys" "dict" "a" "A" "Af" +add hier "concept" "sys" "dict" "a" "A" "Ag" +add hier "concept" "sys" "dict" "a" "A" "Ah" +add hier "concept" "sys" "dict" "a" "A" "Ai" +add hier "concept" "sys" "dict" "a" "A" "Aj" +add hier "concept" "sys" "dict" "a" "A" "Ak" +add hier "concept" "sys" "dict" "a" "A" "Al" +add hier "concept" "sys" "dict" "a" "A" "Am" +add hier "concept" "sys" "dict" "a" "A" "An" +add hier "concept" "sys" "dict" "a" "A" "Ap" +add hier "concept" "sys" "dict" "a" "A" "Aq" +add hier "concept" "sys" "dict" "a" "A" "Ar" +add hier "concept" "sys" "dict" "a" "A" "As" +add hier "concept" "sys" "dict" "a" "A" "At" +add hier "concept" "sys" "dict" "a" "A" "Au" +add hier "concept" "sys" "dict" "a" "A" "Av" +add hier "concept" "sys" "dict" "a" "A" "Aw" +add hier "concept" "sys" "dict" "a" "A" "Ax" +add hier "concept" "sys" "dict" "a" "A" "Ay" +add hier "concept" "sys" "dict" "a" "A" "Az" +add hier "concept" "sys" "dict" "a" "B" +add hier "concept" "sys" "dict" "a" "B" "B" +add hier "concept" "sys" "dict" "a" "B" "Ba" +add hier "concept" "sys" "dict" "a" "B" "Be" +add hier "concept" "sys" "dict" "a" "B" "Bi" +add hier "concept" "sys" "dict" "a" "B" "Bl" +add hier "concept" "sys" "dict" "a" "B" "Bo" +add hier "concept" "sys" "dict" "a" "B" "Br" +add hier "concept" "sys" "dict" "a" "B" "Bu" +add hier "concept" "sys" "dict" "a" "B" "By" +add hier "concept" "sys" "dict" "a" "C" +add hier "concept" "sys" "dict" "a" "C" "C" +add hier "concept" "sys" "dict" "a" "C" "Ca" +add hier "concept" "sys" "dict" "a" "C" "Ce" +add hier "concept" "sys" "dict" "a" "C" "Ch" +add hier "concept" "sys" "dict" "a" "C" "Ci" +add hier "concept" "sys" "dict" "a" "C" "Cl" +add hier "concept" "sys" "dict" "a" "C" "Co" +add hier "concept" "sys" "dict" "a" "C" "Cr" +add hier "concept" "sys" "dict" "a" "C" "Cu" +add hier "concept" "sys" "dict" "a" "C" "Cy" +add hier "concept" "sys" "dict" "a" "D" +add hier "concept" "sys" "dict" "a" "D" "D" +add hier "concept" "sys" "dict" "a" "D" "Da" +add hier "concept" "sys" "dict" "a" "D" "De" +add hier "concept" "sys" "dict" "a" "D" "Di" +add hier "concept" "sys" "dict" "a" "D" "Do" +add hier "concept" "sys" "dict" "a" "D" "Dr" +add hier "concept" "sys" "dict" "a" "D" "Du" +add hier "concept" "sys" "dict" "a" "D" "Dy" +add hier "concept" "sys" "dict" "a" "E" +add hier "concept" "sys" "dict" "a" "E" "E" +add hier "concept" "sys" "dict" "a" "E" "Ea" +add hier "concept" "sys" "dict" "a" "E" "Eb" +add hier "concept" "sys" "dict" "a" "E" "Ed" +add hier "concept" "sys" "dict" "a" "E" "Ee" +add hier "concept" "sys" "dict" "a" "E" "Ef" +add hier "concept" "sys" "dict" "a" "E" "Eg" +add hier "concept" "sys" "dict" "a" "E" "Eh" +add hier "concept" "sys" "dict" "a" "E" "Ei" +add hier "concept" "sys" "dict" "a" "E" "Ej" +add hier "concept" "sys" "dict" "a" "E" "El" +add hier "concept" "sys" "dict" "a" "E" "Em" +add hier "concept" "sys" "dict" "a" "E" "En" +add hier "concept" "sys" "dict" "a" "E" "Eo" +add hier "concept" "sys" "dict" "a" "E" "Ep" +add hier "concept" "sys" "dict" "a" "E" "Eq" +add hier "concept" "sys" "dict" "a" "E" "Er" +add hier "concept" "sys" "dict" "a" "E" "Es" +add hier "concept" "sys" "dict" "a" "E" "Et" +add hier "concept" "sys" "dict" "a" "E" "Eu" +add hier "concept" "sys" "dict" "a" "E" "Ev" +add hier "concept" "sys" "dict" "a" "E" "Ew" +add hier "concept" "sys" "dict" "a" "E" "Ex" +add hier "concept" "sys" "dict" "a" "E" "Ey" +add hier "concept" "sys" "dict" "a" "E" "Ez" +add hier "concept" "sys" "dict" "a" "F" +add hier "concept" "sys" "dict" "a" "F" "F" +add hier "concept" "sys" "dict" "a" "F" "Fa" +add hier "concept" "sys" "dict" "a" "F" "Fe" +add hier "concept" "sys" "dict" "a" "F" "Fi" +add hier "concept" "sys" "dict" "a" "F" "Fl" +add hier "concept" "sys" "dict" "a" "F" "Fo" +add hier "concept" "sys" "dict" "a" "F" "Fr" +add hier "concept" "sys" "dict" "a" "F" "Fu" +add hier "concept" "sys" "dict" "a" "F" "Fy" +add hier "concept" "sys" "dict" "a" "G" +add hier "concept" "sys" "dict" "a" "G" "G" +add hier "concept" "sys" "dict" "a" "G" "Ga" +add hier "concept" "sys" "dict" "a" "G" "Ge" +add hier "concept" "sys" "dict" "a" "G" "Gh" +add hier "concept" "sys" "dict" "a" "G" "Gi" +add hier "concept" "sys" "dict" "a" "G" "Gl" +add hier "concept" "sys" "dict" "a" "G" "Gn" +add hier "concept" "sys" "dict" "a" "G" "Go" +add hier "concept" "sys" "dict" "a" "G" "Gr" +add hier "concept" "sys" "dict" "a" "G" "Gu" +add hier "concept" "sys" "dict" "a" "G" "Gy" +add hier "concept" "sys" "dict" "a" "H" +add hier "concept" "sys" "dict" "a" "H" "H" +add hier "concept" "sys" "dict" "a" "H" "Ha" +add hier "concept" "sys" "dict" "a" "H" "He" +add hier "concept" "sys" "dict" "a" "H" "Hi" +add hier "concept" "sys" "dict" "a" "H" "Ho" +add hier "concept" "sys" "dict" "a" "H" "Hu" +add hier "concept" "sys" "dict" "a" "H" "Hy" +add hier "concept" "sys" "dict" "a" "I" +add hier "concept" "sys" "dict" "a" "I" "I" +add hier "concept" "sys" "dict" "a" "I" "Ia" +add hier "concept" "sys" "dict" "a" "I" "Ib" +add hier "concept" "sys" "dict" "a" "I" "Ic" +add hier "concept" "sys" "dict" "a" "I" "Id" +add hier "concept" "sys" "dict" "a" "I" "Ig" +add hier "concept" "sys" "dict" "a" "I" "Il" +add hier "concept" "sys" "dict" "a" "I" "Im" +add hier "concept" "sys" "dict" "a" "I" "In" +add hier "concept" "sys" "dict" "a" "I" "Io" +add hier "concept" "sys" "dict" "a" "I" "Ir" +add hier "concept" "sys" "dict" "a" "I" "Is" +add hier "concept" "sys" "dict" "a" "I" "It" +add hier "concept" "sys" "dict" "a" "J" +add hier "concept" "sys" "dict" "a" "J" "J" +add hier "concept" "sys" "dict" "a" "J" "Ja" +add hier "concept" "sys" "dict" "a" "J" "Je" +add hier "concept" "sys" "dict" "a" "J" "Ji" +add hier "concept" "sys" "dict" "a" "J" "Jo" +add hier "concept" "sys" "dict" "a" "J" "Ju" +add hier "concept" "sys" "dict" "a" "K" +add hier "concept" "sys" "dict" "a" "K" "K" +add hier "concept" "sys" "dict" "a" "K" "Ka" +add hier "concept" "sys" "dict" "a" "K" "Ke" +add hier "concept" "sys" "dict" "a" "K" "Kh" +add hier "concept" "sys" "dict" "a" "K" "Ki" +add hier "concept" "sys" "dict" "a" "K" "Kl" +add hier "concept" "sys" "dict" "a" "K" "Kn" +add hier "concept" "sys" "dict" "a" "K" "Ko" +add hier "concept" "sys" "dict" "a" "K" "Kr" +add hier "concept" "sys" "dict" "a" "K" "Ku" +add hier "concept" "sys" "dict" "a" "L" +add hier "concept" "sys" "dict" "a" "L" "L" +add hier "concept" "sys" "dict" "a" "L" "La" +add hier "concept" "sys" "dict" "a" "L" "Le" +add hier "concept" "sys" "dict" "a" "L" "Li" +add hier "concept" "sys" "dict" "a" "L" "Ll" +add hier "concept" "sys" "dict" "a" "L" "Lo" +add hier "concept" "sys" "dict" "a" "L" "Lu" +add hier "concept" "sys" "dict" "a" "L" "Ly" +add hier "concept" "sys" "dict" "a" "M" +add hier "concept" "sys" "dict" "a" "M" "M" +add hier "concept" "sys" "dict" "a" "M" "Ma" +add hier "concept" "sys" "dict" "a" "M" "Me" +add hier "concept" "sys" "dict" "a" "M" "Mi" +add hier "concept" "sys" "dict" "a" "M" "Mn" +add hier "concept" "sys" "dict" "a" "M" "Mo" +add hier "concept" "sys" "dict" "a" "M" "Mu" +add hier "concept" "sys" "dict" "a" "M" "My" +add hier "concept" "sys" "dict" "a" "N" +add hier "concept" "sys" "dict" "a" "N" "N" +add hier "concept" "sys" "dict" "a" "N" "Na" +add hier "concept" "sys" "dict" "a" "N" "Ne" +add hier "concept" "sys" "dict" "a" "N" "Ni" +add hier "concept" "sys" "dict" "a" "N" "No" +add hier "concept" "sys" "dict" "a" "N" "Nu" +add hier "concept" "sys" "dict" "a" "N" "Ny" +add hier "concept" "sys" "dict" "a" "O" +add hier "concept" "sys" "dict" "a" "O" "O" +add hier "concept" "sys" "dict" "a" "O" "Oa" +add hier "concept" "sys" "dict" "a" "O" "Ob" +add hier "concept" "sys" "dict" "a" "O" "Oc" +add hier "concept" "sys" "dict" "a" "O" "Od" +add hier "concept" "sys" "dict" "a" "O" "Oe" +add hier "concept" "sys" "dict" "a" "O" "Of" +add hier "concept" "sys" "dict" "a" "O" "Og" +add hier "concept" "sys" "dict" "a" "O" "Oh" +add hier "concept" "sys" "dict" "a" "O" "Oi" +add hier "concept" "sys" "dict" "a" "O" "Ok" +add hier "concept" "sys" "dict" "a" "O" "On" +add hier "concept" "sys" "dict" "a" "O" "Oo" +add hier "concept" "sys" "dict" "a" "O" "Op" +add hier "concept" "sys" "dict" "a" "O" "Oq" +add hier "concept" "sys" "dict" "a" "O" "Or" +add hier "concept" "sys" "dict" "a" "O" "Os" +add hier "concept" "sys" "dict" "a" "O" "Ot" +add hier "concept" "sys" "dict" "a" "O" "Ou" +add hier "concept" "sys" "dict" "a" "O" "Ov" +add hier "concept" "sys" "dict" "a" "O" "Ow" +add hier "concept" "sys" "dict" "a" "O" "Ox" +add hier "concept" "sys" "dict" "a" "O" "Oy" +add hier "concept" "sys" "dict" "a" "O" "Oz" +add hier "concept" "sys" "dict" "a" "P" +add hier "concept" "sys" "dict" "a" "P" "P" +add hier "concept" "sys" "dict" "a" "P" "Pa" +add hier "concept" "sys" "dict" "a" "P" "Pe" +add hier "concept" "sys" "dict" "a" "P" "Ph" +add hier "concept" "sys" "dict" "a" "P" "Pi" +add hier "concept" "sys" "dict" "a" "P" "Pl" +add hier "concept" "sys" "dict" "a" "P" "Pn" +add hier "concept" "sys" "dict" "a" "P" "Po" +add hier "concept" "sys" "dict" "a" "P" "Pr" +add hier "concept" "sys" "dict" "a" "P" "Pt" +add hier "concept" "sys" "dict" "a" "P" "Pu" +add hier "concept" "sys" "dict" "a" "P" "Py" +add hier "concept" "sys" "dict" "a" "Q" +add hier "concept" "sys" "dict" "a" "Q" "Q" +add hier "concept" "sys" "dict" "a" "Q" "Qa" +add hier "concept" "sys" "dict" "a" "Q" "Qu" +add hier "concept" "sys" "dict" "a" "R" +add hier "concept" "sys" "dict" "a" "R" "R" +add hier "concept" "sys" "dict" "a" "R" "Ra" +add hier "concept" "sys" "dict" "a" "R" "Re" +add hier "concept" "sys" "dict" "a" "R" "Rh" +add hier "concept" "sys" "dict" "a" "R" "Ri" +add hier "concept" "sys" "dict" "a" "R" "Ro" +add hier "concept" "sys" "dict" "a" "R" "Ru" +add hier "concept" "sys" "dict" "a" "R" "Ry" +add hier "concept" "sys" "dict" "a" "S" +add hier "concept" "sys" "dict" "a" "S" "S" +add hier "concept" "sys" "dict" "a" "S" "Sa" +add hier "concept" "sys" "dict" "a" "S" "Sc" +add hier "concept" "sys" "dict" "a" "S" "Se" +add hier "concept" "sys" "dict" "a" "S" "Sf" +add hier "concept" "sys" "dict" "a" "S" "Sh" +add hier "concept" "sys" "dict" "a" "S" "Si" +add hier "concept" "sys" "dict" "a" "S" "Sk" +add hier "concept" "sys" "dict" "a" "S" "Sl" +add hier "concept" "sys" "dict" "a" "S" "Sm" +add hier "concept" "sys" "dict" "a" "S" "Sn" +add hier "concept" "sys" "dict" "a" "S" "So" +add hier "concept" "sys" "dict" "a" "S" "Sp" +add hier "concept" "sys" "dict" "a" "S" "Sq" +add hier "concept" "sys" "dict" "a" "S" "St" +add hier "concept" "sys" "dict" "a" "S" "Su" +add hier "concept" "sys" "dict" "a" "S" "Sw" +add hier "concept" "sys" "dict" "a" "S" "Sy" +add hier "concept" "sys" "dict" "a" "T" +add hier "concept" "sys" "dict" "a" "T" "T" +add hier "concept" "sys" "dict" "a" "T" "Ta" +add hier "concept" "sys" "dict" "a" "T" "Te" +add hier "concept" "sys" "dict" "a" "T" "Th" +add hier "concept" "sys" "dict" "a" "T" "Ti" +add hier "concept" "sys" "dict" "a" "T" "To" +add hier "concept" "sys" "dict" "a" "T" "Tr" +add hier "concept" "sys" "dict" "a" "T" "Tu" +add hier "concept" "sys" "dict" "a" "T" "Tw" +add hier "concept" "sys" "dict" "a" "T" "Ty" +add hier "concept" "sys" "dict" "a" "U" +add hier "concept" "sys" "dict" "a" "U" "U" +add hier "concept" "sys" "dict" "a" "U" "Ua" +add hier "concept" "sys" "dict" "a" "U" "Un" +add hier "concept" "sys" "dict" "a" "U" "Up" +add hier "concept" "sys" "dict" "a" "U" "Ur" +add hier "concept" "sys" "dict" "a" "V" +add hier "concept" "sys" "dict" "a" "V" "V" +add hier "concept" "sys" "dict" "a" "V" "Va" +add hier "concept" "sys" "dict" "a" "V" "Ve" +add hier "concept" "sys" "dict" "a" "V" "Vi" +add hier "concept" "sys" "dict" "a" "V" "Vo" +add hier "concept" "sys" "dict" "a" "V" "Vu" +add hier "concept" "sys" "dict" "a" "W" +add hier "concept" "sys" "dict" "a" "W" "W" +add hier "concept" "sys" "dict" "a" "W" "Wa" +add hier "concept" "sys" "dict" "a" "W" "We" +add hier "concept" "sys" "dict" "a" "W" "Wh" +add hier "concept" "sys" "dict" "a" "W" "Wi" +add hier "concept" "sys" "dict" "a" "W" "Wo" +add hier "concept" "sys" "dict" "a" "W" "Wr" +add hier "concept" "sys" "dict" "a" "W" "Wu" +add hier "concept" "sys" "dict" "a" "X" +add hier "concept" "sys" "dict" "a" "X" "X" +add hier "concept" "sys" "dict" "a" "X" "Xa" +add hier "concept" "sys" "dict" "a" "X" "Xe" +add hier "concept" "sys" "dict" "a" "X" "Xi" +add hier "concept" "sys" "dict" "a" "X" "Xo" +add hier "concept" "sys" "dict" "a" "X" "Xu" +add hier "concept" "sys" "dict" "a" "X" "Xy" +add hier "concept" "sys" "dict" "a" "Y" +add hier "concept" "sys" "dict" "a" "Y" "Y" +add hier "concept" "sys" "dict" "a" "Y" "Ya" +add hier "concept" "sys" "dict" "a" "Y" "Ye" +add hier "concept" "sys" "dict" "a" "Y" "Yi" +add hier "concept" "sys" "dict" "a" "Y" "Yo" +add hier "concept" "sys" "dict" "a" "Y" "Yu" +add hier "concept" "sys" "dict" "a" "Z" +add hier "concept" "sys" "dict" "a" "Z" "Z" +add hier "concept" "sys" "dict" "a" "Z" "Za" +add hier "concept" "sys" "dict" "a" "Z" "Ze" +add hier "concept" "sys" "dict" "a" "Z" "Zi" +add hier "concept" "sys" "dict" "a" "Z" "Zo" +add hier "concept" "sys" "dict" "a" "Z" "Zu" +add hier "concept" "sys" "dict" "a" "Z" "Zy" +add hier "concept" "sys" "dict" "a" "a" +add hier "concept" "sys" "dict" "a" "a" "a" +add hier "concept" "sys" "dict" "a" "a" "aa" +add hier "concept" "sys" "dict" "a" "a" "ab" +add hier "concept" "sys" "dict" "a" "a" "ac" +add hier "concept" "sys" "dict" "a" "a" "ad" +add hier "concept" "sys" "dict" "a" "a" "ae" +add hier "concept" "sys" "dict" "a" "a" "af" +add hier "concept" "sys" "dict" "a" "a" "ag" +add hier "concept" "sys" "dict" "a" "a" "ah" +add hier "concept" "sys" "dict" "a" "a" "ai" +add hier "concept" "sys" "dict" "a" "a" "aj" +add hier "concept" "sys" "dict" "a" "a" "ak" +add hier "concept" "sys" "dict" "a" "a" "al" +add hier "concept" "sys" "dict" "a" "a" "am" +add hier "concept" "sys" "dict" "a" "a" "an" +add hier "concept" "sys" "dict" "a" "a" "ap" +add hier "concept" "sys" "dict" "a" "a" "aq" +add hier "concept" "sys" "dict" "a" "a" "ar" +add hier "concept" "sys" "dict" "a" "a" "as" +add hier "concept" "sys" "dict" "a" "a" "at" +add hier "concept" "sys" "dict" "a" "a" "au" +add hier "concept" "sys" "dict" "a" "a" "av" +add hier "concept" "sys" "dict" "a" "a" "aw" +add hier "concept" "sys" "dict" "a" "a" "ax" +add hier "concept" "sys" "dict" "a" "a" "ay" +add hier "concept" "sys" "dict" "a" "a" "az" +add hier "concept" "sys" "dict" "a" "b" +add hier "concept" "sys" "dict" "a" "b" "b" +add hier "concept" "sys" "dict" "a" "b" "ba" +add hier "concept" "sys" "dict" "a" "b" "be" +add hier "concept" "sys" "dict" "a" "b" "bi" +add hier "concept" "sys" "dict" "a" "b" "bl" +add hier "concept" "sys" "dict" "a" "b" "bo" +add hier "concept" "sys" "dict" "a" "b" "br" +add hier "concept" "sys" "dict" "a" "b" "bu" +add hier "concept" "sys" "dict" "a" "b" "by" +add hier "concept" "sys" "dict" "a" "c" +add hier "concept" "sys" "dict" "a" "c" "c" +add hier "concept" "sys" "dict" "a" "c" "ca" +add hier "concept" "sys" "dict" "a" "c" "ce" +add hier "concept" "sys" "dict" "a" "c" "ch" +add hier "concept" "sys" "dict" "a" "c" "ci" +add hier "concept" "sys" "dict" "a" "c" "cl" +add hier "concept" "sys" "dict" "a" "c" "co" +add hier "concept" "sys" "dict" "a" "c" "cr" +add hier "concept" "sys" "dict" "a" "c" "cu" +add hier "concept" "sys" "dict" "a" "c" "cy" +add hier "concept" "sys" "dict" "a" "d" +add hier "concept" "sys" "dict" "a" "d" "d" +add hier "concept" "sys" "dict" "a" "d" "da" +add hier "concept" "sys" "dict" "a" "d" "de" +add hier "concept" "sys" "dict" "a" "d" "di" +add hier "concept" "sys" "dict" "a" "d" "do" +add hier "concept" "sys" "dict" "a" "d" "dr" +add hier "concept" "sys" "dict" "a" "d" "du" +add hier "concept" "sys" "dict" "a" "d" "dy" +add hier "concept" "sys" "dict" "a" "e" +add hier "concept" "sys" "dict" "a" "e" "e" +add hier "concept" "sys" "dict" "a" "e" "ea" +add hier "concept" "sys" "dict" "a" "e" "eb" +add hier "concept" "sys" "dict" "a" "e" "ed" +add hier "concept" "sys" "dict" "a" "e" "ee" +add hier "concept" "sys" "dict" "a" "e" "ef" +add hier "concept" "sys" "dict" "a" "e" "eg" +add hier "concept" "sys" "dict" "a" "e" "eh" +add hier "concept" "sys" "dict" "a" "e" "ei" +add hier "concept" "sys" "dict" "a" "e" "ej" +add hier "concept" "sys" "dict" "a" "e" "el" +add hier "concept" "sys" "dict" "a" "e" "em" +add hier "concept" "sys" "dict" "a" "e" "en" +add hier "concept" "sys" "dict" "a" "e" "eo" +add hier "concept" "sys" "dict" "a" "e" "ep" +add hier "concept" "sys" "dict" "a" "e" "eq" +add hier "concept" "sys" "dict" "a" "e" "er" +add hier "concept" "sys" "dict" "a" "e" "es" +add hier "concept" "sys" "dict" "a" "e" "et" +add hier "concept" "sys" "dict" "a" "e" "eu" +add hier "concept" "sys" "dict" "a" "e" "ev" +add hier "concept" "sys" "dict" "a" "e" "ew" +add hier "concept" "sys" "dict" "a" "e" "ex" +add hier "concept" "sys" "dict" "a" "e" "ey" +add hier "concept" "sys" "dict" "a" "e" "ez" +add hier "concept" "sys" "dict" "a" "f" +add hier "concept" "sys" "dict" "a" "f" "f" +add hier "concept" "sys" "dict" "a" "f" "fa" +add hier "concept" "sys" "dict" "a" "f" "fe" +add hier "concept" "sys" "dict" "a" "f" "fi" +add hier "concept" "sys" "dict" "a" "f" "fl" +add hier "concept" "sys" "dict" "a" "f" "fo" +add hier "concept" "sys" "dict" "a" "f" "fr" +add hier "concept" "sys" "dict" "a" "f" "fu" +add hier "concept" "sys" "dict" "a" "f" "fy" +add hier "concept" "sys" "dict" "a" "g" +add hier "concept" "sys" "dict" "a" "g" "g" +add hier "concept" "sys" "dict" "a" "g" "ga" +add hier "concept" "sys" "dict" "a" "g" "ge" +add hier "concept" "sys" "dict" "a" "g" "gh" +add hier "concept" "sys" "dict" "a" "g" "gi" +add hier "concept" "sys" "dict" "a" "g" "gl" +add hier "concept" "sys" "dict" "a" "g" "gn" +add hier "concept" "sys" "dict" "a" "g" "go" +add hier "concept" "sys" "dict" "a" "g" "gr" +add hier "concept" "sys" "dict" "a" "g" "gu" +add hier "concept" "sys" "dict" "a" "g" "gy" +add hier "concept" "sys" "dict" "a" "h" +add hier "concept" "sys" "dict" "a" "h" "h" +add hier "concept" "sys" "dict" "a" "h" "ha" +add hier "concept" "sys" "dict" "a" "h" "he" +add hier "concept" "sys" "dict" "a" "h" "hi" +add hier "concept" "sys" "dict" "a" "h" "ho" +add hier "concept" "sys" "dict" "a" "h" "hu" +add hier "concept" "sys" "dict" "a" "h" "hy" +add hier "concept" "sys" "dict" "a" "i" +add hier "concept" "sys" "dict" "a" "i" "i" +add hier "concept" "sys" "dict" "a" "i" "ia" +add hier "concept" "sys" "dict" "a" "i" "ib" +add hier "concept" "sys" "dict" "a" "i" "ic" +add hier "concept" "sys" "dict" "a" "i" "id" +add hier "concept" "sys" "dict" "a" "i" "ig" +add hier "concept" "sys" "dict" "a" "i" "il" +add hier "concept" "sys" "dict" "a" "i" "im" +add hier "concept" "sys" "dict" "a" "i" "in" +add hier "concept" "sys" "dict" "a" "i" "io" +add hier "concept" "sys" "dict" "a" "i" "ir" +add hier "concept" "sys" "dict" "a" "i" "is" +add hier "concept" "sys" "dict" "a" "i" "it" +add hier "concept" "sys" "dict" "a" "j" +add hier "concept" "sys" "dict" "a" "j" "j" +add hier "concept" "sys" "dict" "a" "j" "ja" +add hier "concept" "sys" "dict" "a" "j" "je" +add hier "concept" "sys" "dict" "a" "j" "ji" +add hier "concept" "sys" "dict" "a" "j" "jo" +add hier "concept" "sys" "dict" "a" "j" "ju" +add hier "concept" "sys" "dict" "a" "k" +add hier "concept" "sys" "dict" "a" "k" "k" +add hier "concept" "sys" "dict" "a" "k" "ka" +add hier "concept" "sys" "dict" "a" "k" "ke" +add hier "concept" "sys" "dict" "a" "k" "kh" +add hier "concept" "sys" "dict" "a" "k" "ki" +add hier "concept" "sys" "dict" "a" "k" "kl" +add hier "concept" "sys" "dict" "a" "k" "kn" +add hier "concept" "sys" "dict" "a" "k" "ko" +add hier "concept" "sys" "dict" "a" "k" "kr" +add hier "concept" "sys" "dict" "a" "k" "ku" +add hier "concept" "sys" "dict" "a" "l" +add hier "concept" "sys" "dict" "a" "l" "l" +add hier "concept" "sys" "dict" "a" "l" "la" +add hier "concept" "sys" "dict" "a" "l" "le" +add hier "concept" "sys" "dict" "a" "l" "li" +add hier "concept" "sys" "dict" "a" "l" "ll" +add hier "concept" "sys" "dict" "a" "l" "lo" +add hier "concept" "sys" "dict" "a" "l" "lu" +add hier "concept" "sys" "dict" "a" "l" "ly" +add hier "concept" "sys" "dict" "a" "m" +add hier "concept" "sys" "dict" "a" "m" "m" +add hier "concept" "sys" "dict" "a" "m" "ma" +add hier "concept" "sys" "dict" "a" "m" "me" +add hier "concept" "sys" "dict" "a" "m" "mi" +add hier "concept" "sys" "dict" "a" "m" "mn" +add hier "concept" "sys" "dict" "a" "m" "mo" +add hier "concept" "sys" "dict" "a" "m" "mu" +add hier "concept" "sys" "dict" "a" "m" "my" +add hier "concept" "sys" "dict" "a" "n" +add hier "concept" "sys" "dict" "a" "n" "n" +add hier "concept" "sys" "dict" "a" "n" "na" +add hier "concept" "sys" "dict" "a" "n" "ne" +add hier "concept" "sys" "dict" "a" "n" "ni" +add hier "concept" "sys" "dict" "a" "n" "no" +add hier "concept" "sys" "dict" "a" "n" "nu" +add hier "concept" "sys" "dict" "a" "n" "ny" +add hier "concept" "sys" "dict" "a" "o" +add hier "concept" "sys" "dict" "a" "o" "o" +add hier "concept" "sys" "dict" "a" "o" "oa" +add hier "concept" "sys" "dict" "a" "o" "ob" +add hier "concept" "sys" "dict" "a" "o" "oc" +add hier "concept" "sys" "dict" "a" "o" "od" +add hier "concept" "sys" "dict" "a" "o" "oe" +add hier "concept" "sys" "dict" "a" "o" "of" +add hier "concept" "sys" "dict" "a" "o" "og" +add hier "concept" "sys" "dict" "a" "o" "oh" +add hier "concept" "sys" "dict" "a" "o" "oi" +add hier "concept" "sys" "dict" "a" "o" "ok" +add hier "concept" "sys" "dict" "a" "o" "on" +add hier "concept" "sys" "dict" "a" "o" "oo" +add hier "concept" "sys" "dict" "a" "o" "op" +add hier "concept" "sys" "dict" "a" "o" "oq" +add hier "concept" "sys" "dict" "a" "o" "or" +add hier "concept" "sys" "dict" "a" "o" "os" +add hier "concept" "sys" "dict" "a" "o" "ot" +add hier "concept" "sys" "dict" "a" "o" "ou" +add hier "concept" "sys" "dict" "a" "o" "ov" +add hier "concept" "sys" "dict" "a" "o" "ow" +add hier "concept" "sys" "dict" "a" "o" "ox" +add hier "concept" "sys" "dict" "a" "o" "oy" +add hier "concept" "sys" "dict" "a" "o" "oz" +add hier "concept" "sys" "dict" "a" "p" +add hier "concept" "sys" "dict" "a" "p" "p" +add hier "concept" "sys" "dict" "a" "p" "pa" +add hier "concept" "sys" "dict" "a" "p" "pe" +add hier "concept" "sys" "dict" "a" "p" "ph" +add hier "concept" "sys" "dict" "a" "p" "pi" +add hier "concept" "sys" "dict" "a" "p" "pl" +add hier "concept" "sys" "dict" "a" "p" "pn" +add hier "concept" "sys" "dict" "a" "p" "po" +add hier "concept" "sys" "dict" "a" "p" "pr" +add hier "concept" "sys" "dict" "a" "p" "pt" +add hier "concept" "sys" "dict" "a" "p" "pu" +add hier "concept" "sys" "dict" "a" "p" "py" +add hier "concept" "sys" "dict" "a" "q" +add hier "concept" "sys" "dict" "a" "q" "q" +add hier "concept" "sys" "dict" "a" "q" "qa" +add hier "concept" "sys" "dict" "a" "q" "qu" +add hier "concept" "sys" "dict" "a" "r" +add hier "concept" "sys" "dict" "a" "r" "r" +add hier "concept" "sys" "dict" "a" "r" "ra" +add hier "concept" "sys" "dict" "a" "r" "re" +add hier "concept" "sys" "dict" "a" "r" "rh" +add hier "concept" "sys" "dict" "a" "r" "ri" +add hier "concept" "sys" "dict" "a" "r" "ro" +add hier "concept" "sys" "dict" "a" "r" "ru" +add hier "concept" "sys" "dict" "a" "r" "ry" +add hier "concept" "sys" "dict" "a" "s" +add hier "concept" "sys" "dict" "a" "s" "s" +add hier "concept" "sys" "dict" "a" "s" "sa" +add hier "concept" "sys" "dict" "a" "s" "sc" +add hier "concept" "sys" "dict" "a" "s" "se" +add hier "concept" "sys" "dict" "a" "s" "sf" +add hier "concept" "sys" "dict" "a" "s" "sh" +add hier "concept" "sys" "dict" "a" "s" "si" +add hier "concept" "sys" "dict" "a" "s" "sk" +add hier "concept" "sys" "dict" "a" "s" "sl" +add hier "concept" "sys" "dict" "a" "s" "sm" +add hier "concept" "sys" "dict" "a" "s" "sn" +add hier "concept" "sys" "dict" "a" "s" "so" +add hier "concept" "sys" "dict" "a" "s" "sp" +add hier "concept" "sys" "dict" "a" "s" "sq" +add hier "concept" "sys" "dict" "a" "s" "st" +add hier "concept" "sys" "dict" "a" "s" "su" +add hier "concept" "sys" "dict" "a" "s" "sw" +add hier "concept" "sys" "dict" "a" "s" "sy" +add hier "concept" "sys" "dict" "a" "t" +add hier "concept" "sys" "dict" "a" "t" "t" +add hier "concept" "sys" "dict" "a" "t" "ta" +add hier "concept" "sys" "dict" "a" "t" "te" +add hier "concept" "sys" "dict" "a" "t" "th" +add hier "concept" "sys" "dict" "a" "t" "ti" +add hier "concept" "sys" "dict" "a" "t" "to" +add hier "concept" "sys" "dict" "a" "t" "tr" +add hier "concept" "sys" "dict" "a" "t" "tu" +add hier "concept" "sys" "dict" "a" "t" "tw" +add hier "concept" "sys" "dict" "a" "t" "ty" +add hier "concept" "sys" "dict" "a" "u" +add hier "concept" "sys" "dict" "a" "u" "u" +add hier "concept" "sys" "dict" "a" "u" "ua" +add hier "concept" "sys" "dict" "a" "u" "un" +add hier "concept" "sys" "dict" "a" "u" "up" +add hier "concept" "sys" "dict" "a" "u" "ur" +add hier "concept" "sys" "dict" "a" "v" +add hier "concept" "sys" "dict" "a" "v" "v" +add hier "concept" "sys" "dict" "a" "v" "va" +add hier "concept" "sys" "dict" "a" "v" "ve" +add hier "concept" "sys" "dict" "a" "v" "vi" +add hier "concept" "sys" "dict" "a" "v" "vo" +add hier "concept" "sys" "dict" "a" "v" "vu" +add hier "concept" "sys" "dict" "a" "w" +add hier "concept" "sys" "dict" "a" "w" "w" +add hier "concept" "sys" "dict" "a" "w" "wa" +add hier "concept" "sys" "dict" "a" "w" "we" +add hier "concept" "sys" "dict" "a" "w" "wh" +add hier "concept" "sys" "dict" "a" "w" "wi" +add hier "concept" "sys" "dict" "a" "w" "wo" +add hier "concept" "sys" "dict" "a" "w" "wr" +add hier "concept" "sys" "dict" "a" "w" "wu" +add hier "concept" "sys" "dict" "a" "x" +add hier "concept" "sys" "dict" "a" "x" "x" +add hier "concept" "sys" "dict" "a" "x" "xa" +add hier "concept" "sys" "dict" "a" "x" "xe" +add hier "concept" "sys" "dict" "a" "x" "xi" +add hier "concept" "sys" "dict" "a" "x" "xo" +add hier "concept" "sys" "dict" "a" "x" "xu" +add hier "concept" "sys" "dict" "a" "x" "xy" +add hier "concept" "sys" "dict" "a" "y" +add hier "concept" "sys" "dict" "a" "y" "y" +add hier "concept" "sys" "dict" "a" "y" "ya" +add hier "concept" "sys" "dict" "a" "y" "ye" +add hier "concept" "sys" "dict" "a" "y" "yi" +add hier "concept" "sys" "dict" "a" "y" "yo" +add hier "concept" "sys" "dict" "a" "y" "yu" +add hier "concept" "sys" "dict" "a" "z" +add hier "concept" "sys" "dict" "a" "z" "z" +add hier "concept" "sys" "dict" "a" "z" "za" +add hier "concept" "sys" "dict" "a" "z" "ze" +add hier "concept" "sys" "dict" "a" "z" "zi" +add hier "concept" "sys" "dict" "a" "z" "zo" +add hier "concept" "sys" "dict" "a" "z" "zu" +add hier "concept" "sys" "dict" "a" "z" "zy" +add hier "concept" "sys" "dict" "0" +add hier "concept" "sys" "dict" "0" "0" +add hier "concept" "sys" "dict" "0" "0" "0" +add hier "concept" "sys" "dict" "0" "0" "00" +add hier "concept" "sys" "dict" "0" "0" "01" +add hier "concept" "sys" "dict" "0" "0" "02" +add hier "concept" "sys" "dict" "0" "0" "03" +add hier "concept" "sys" "dict" "0" "0" "04" +add hier "concept" "sys" "dict" "0" "0" "05" +add hier "concept" "sys" "dict" "0" "0" "06" +add hier "concept" "sys" "dict" "0" "0" "07" +add hier "concept" "sys" "dict" "0" "0" "08" +add hier "concept" "sys" "dict" "0" "0" "09" +add hier "concept" "sys" "dict" "0" "1" +add hier "concept" "sys" "dict" "0" "1" "1" +add hier "concept" "sys" "dict" "0" "1" "10" +add hier "concept" "sys" "dict" "0" "1" "11" +add hier "concept" "sys" "dict" "0" "1" "12" +add hier "concept" "sys" "dict" "0" "1" "13" +add hier "concept" "sys" "dict" "0" "1" "14" +add hier "concept" "sys" "dict" "0" "1" "15" +add hier "concept" "sys" "dict" "0" "1" "16" +add hier "concept" "sys" "dict" "0" "1" "17" +add hier "concept" "sys" "dict" "0" "1" "18" +add hier "concept" "sys" "dict" "0" "1" "19" +add hier "concept" "sys" "dict" "0" "2" +add hier "concept" "sys" "dict" "0" "2" "2" +add hier "concept" "sys" "dict" "0" "2" "20" +add hier "concept" "sys" "dict" "0" "2" "21" +add hier "concept" "sys" "dict" "0" "2" "22" +add hier "concept" "sys" "dict" "0" "2" "23" +add hier "concept" "sys" "dict" "0" "2" "24" +add hier "concept" "sys" "dict" "0" "2" "25" +add hier "concept" "sys" "dict" "0" "2" "26" +add hier "concept" "sys" "dict" "0" "2" "27" +add hier "concept" "sys" "dict" "0" "2" "28" +add hier "concept" "sys" "dict" "0" "2" "29" +add hier "concept" "sys" "dict" "0" "3" +add hier "concept" "sys" "dict" "0" "3" "3" +add hier "concept" "sys" "dict" "0" "3" "30" +add hier "concept" "sys" "dict" "0" "3" "31" +add hier "concept" "sys" "dict" "0" "3" "32" +add hier "concept" "sys" "dict" "0" "3" "33" +add hier "concept" "sys" "dict" "0" "3" "34" +add hier "concept" "sys" "dict" "0" "3" "35" +add hier "concept" "sys" "dict" "0" "3" "36" +add hier "concept" "sys" "dict" "0" "3" "37" +add hier "concept" "sys" "dict" "0" "3" "38" +add hier "concept" "sys" "dict" "0" "3" "39" +add hier "concept" "sys" "dict" "0" "4" +add hier "concept" "sys" "dict" "0" "4" "4" +add hier "concept" "sys" "dict" "0" "4" "40" +add hier "concept" "sys" "dict" "0" "4" "41" +add hier "concept" "sys" "dict" "0" "4" "42" +add hier "concept" "sys" "dict" "0" "4" "43" +add hier "concept" "sys" "dict" "0" "4" "44" +add hier "concept" "sys" "dict" "0" "4" "45" +add hier "concept" "sys" "dict" "0" "4" "46" +add hier "concept" "sys" "dict" "0" "4" "47" +add hier "concept" "sys" "dict" "0" "4" "48" +add hier "concept" "sys" "dict" "0" "4" "49" +add hier "concept" "sys" "dict" "0" "5" +add hier "concept" "sys" "dict" "0" "5" "5" +add hier "concept" "sys" "dict" "0" "5" "50" +add hier "concept" "sys" "dict" "0" "5" "51" +add hier "concept" "sys" "dict" "0" "5" "52" +add hier "concept" "sys" "dict" "0" "5" "53" +add hier "concept" "sys" "dict" "0" "5" "54" +add hier "concept" "sys" "dict" "0" "5" "55" +add hier "concept" "sys" "dict" "0" "5" "56" +add hier "concept" "sys" "dict" "0" "5" "57" +add hier "concept" "sys" "dict" "0" "5" "58" +add hier "concept" "sys" "dict" "0" "5" "59" +add hier "concept" "sys" "dict" "0" "6" +add hier "concept" "sys" "dict" "0" "6" "6" +add hier "concept" "sys" "dict" "0" "6" "60" +add hier "concept" "sys" "dict" "0" "6" "61" +add hier "concept" "sys" "dict" "0" "6" "62" +add hier "concept" "sys" "dict" "0" "6" "63" +add hier "concept" "sys" "dict" "0" "6" "64" +add hier "concept" "sys" "dict" "0" "6" "65" +add hier "concept" "sys" "dict" "0" "6" "66" +add hier "concept" "sys" "dict" "0" "6" "67" +add hier "concept" "sys" "dict" "0" "6" "68" +add hier "concept" "sys" "dict" "0" "6" "69" +add hier "concept" "sys" "dict" "0" "7" +add hier "concept" "sys" "dict" "0" "7" "7" +add hier "concept" "sys" "dict" "0" "7" "70" +add hier "concept" "sys" "dict" "0" "7" "71" +add hier "concept" "sys" "dict" "0" "7" "72" +add hier "concept" "sys" "dict" "0" "7" "73" +add hier "concept" "sys" "dict" "0" "7" "74" +add hier "concept" "sys" "dict" "0" "7" "75" +add hier "concept" "sys" "dict" "0" "7" "76" +add hier "concept" "sys" "dict" "0" "7" "77" +add hier "concept" "sys" "dict" "0" "7" "78" +add hier "concept" "sys" "dict" "0" "7" "79" +add hier "concept" "sys" "dict" "0" "8" +add hier "concept" "sys" "dict" "0" "8" "8" +add hier "concept" "sys" "dict" "0" "8" "80" +add hier "concept" "sys" "dict" "0" "8" "81" +add hier "concept" "sys" "dict" "0" "8" "82" +add hier "concept" "sys" "dict" "0" "8" "83" +add hier "concept" "sys" "dict" "0" "8" "84" +add hier "concept" "sys" "dict" "0" "8" "85" +add hier "concept" "sys" "dict" "0" "8" "86" +add hier "concept" "sys" "dict" "0" "8" "87" +add hier "concept" "sys" "dict" "0" "8" "88" +add hier "concept" "sys" "dict" "0" "8" "89" +add hier "concept" "sys" "dict" "0" "9" +add hier "concept" "sys" "dict" "0" "9" "9" +add hier "concept" "sys" "dict" "0" "9" "90" +add hier "concept" "sys" "dict" "0" "9" "91" +add hier "concept" "sys" "dict" "0" "9" "92" +add hier "concept" "sys" "dict" "0" "9" "93" +add hier "concept" "sys" "dict" "0" "9" "94" +add hier "concept" "sys" "dict" "0" "9" "95" +add hier "concept" "sys" "dict" "0" "9" "96" +add hier "concept" "sys" "dict" "0" "9" "97" +add hier "concept" "sys" "dict" "0" "9" "98" +add hier "concept" "sys" "dict" "0" "9" "99" +add hier "concept" "sys" "dict" "A" +add hier "concept" "sys" "dict" "wht" +add hier "concept" "sys" "dict" "pnct" +add hier "concept" "sys" "dict" "ctrl" +add hier "concept" "sys" "dict" "emoji" +add hier "concept" "sys" "dict" "unknown" + +quit + diff --git a/.github/workflows/tests/call-analyzer/spec/analyzer.seq b/.github/workflows/tests/call-analyzer/spec/analyzer.seq new file mode 100644 index 00000000..31421e8a --- /dev/null +++ b/.github/workflows/tests/call-analyzer/spec/analyzer.seq @@ -0,0 +1,4 @@ +dicttokz nil # tokenize; this analyzer has no dictionary of its own +nlp sentence # group each sentence +nlp call # hand each sentence node to call-analyzer-callee +nlp report # print the shared tree and KB afterward diff --git a/.github/workflows/tests/call-analyzer/spec/call.nlp b/.github/workflows/tests/call-analyzer/spec/call.nlp new file mode 100644 index 00000000..aad9c39a --- /dev/null +++ b/.github/workflows/tests/call-analyzer/spec/call.nlp @@ -0,0 +1,21 @@ +############################################### +# FILE: call.nlp +# SUBJ: Regression for callanalyzer: hand each sentence node to +# another analyzer, which works on that part of this tree and +# puts what it finds in the given concept of this KB. +# NOTE: The called analyzer lives beside this one, in +# tests/call-analyzer-callee, and is found by name. +############################################### + +@CODE +G("results") = makeconcept(findroot(),"results"); +G("mine") = "caller"; +"out.txt" << "loaded-before:" << str(findana("call-analyzer-callee")) << "\n"; +@@CODE + +@POST +L("s") = makeconcept(G("results"),"sent"); +"out.txt" << "call:" << str(callanalyzer(N(1),L("s"),"call-analyzer-callee")) << "\n"; + +@RULES +_xNIL <- _sent @@ diff --git a/.github/workflows/tests/call-analyzer/spec/report.nlp b/.github/workflows/tests/call-analyzer/spec/report.nlp new file mode 100644 index 00000000..87c2cf62 --- /dev/null +++ b/.github/workflows/tests/call-analyzer/spec/report.nlp @@ -0,0 +1,72 @@ +############################################### +# FILE: report.nlp +# SUBJ: Print what callanalyzer did to the shared tree and KB. +# NOTE: What each line proves: +# loaded-* the called analyzer was loaded by the first call +# mine its G() variables are its own +# tree it changed only the sentence nodes it was given: +# colors became _color nodes and * marks each word +# it visited; the top-level "Blue" is untouched +# _color red/green come from its regular dictionary, loaded +# into the shared KB; crimson only from its lazy +# shades-full.dict, looked up on the passed text +# concept it wrote into this KB's concept directly, saw the +# given node as its root, and could not call back +# self an analyzer cannot call itself +# missing an unknown analyzer is an error, not a crash +# +# Expected out.txt: +# loaded-before:0 +# call:1 +# call:1 +# loaded-after:1 +# mine:caller +# tree:_sent _color apples* . +# tree:_sent _color sky* and* _color grass* . +# tree:Blue +# concept:sent root:_sent sawcallerG:0 backcall:0 colors:red; +# concept:sent root:_sent sawcallerG:0 backcall:0 colors:crimson;green; +# self:0 +# missing:0 +############################################### + +@CODE +"out.txt" << "loaded-after:" << str(findana("call-analyzer-callee")) << "\n"; +"out.txt" << "mine:" << G("mine") << "\n"; + +L("n") = pndown(pnroot()); +while (L("n")) { + "out.txt" << "tree:" << pnname(L("n")); + if (pnvar(L("n"),"callee")) + "out.txt" << "*"; + L("c") = pndown(L("n")); + while (L("c")) { + "out.txt" << " " << pnname(L("c")); + if (pnvar(L("c"),"callee")) + "out.txt" << "*"; + L("c") = pnnext(L("c")); + } + "out.txt" << "\n"; + L("n") = pnnext(L("n")); +} + +L("s") = down(G("results")); +while (L("s")) { + "out.txt" + << "concept:" << conceptname(L("s")) + << " root:" << strval(L("s"),"root") + << " sawcallerG:" << str(numval(L("s"),"sawcallerG")) + << " backcall:" << str(numval(L("s"),"backcall")) + << " colors:"; + L("v") = attrvals(findattr(L("s"),"color")); + while (L("v")) { + "out.txt" << getstrval(L("v")) << ";"; + L("v") = nextval(L("v")); + } + "out.txt" << "\n"; + L("s") = next(L("s")); +} + +"out.txt" << "self:" << str(callanalyzer(pnroot(),G("results"),"call-analyzer")) << "\n"; +"out.txt" << "missing:" << str(callanalyzer(pnroot(),G("results"),"no-such-analyzer")) << "\n"; +@@CODE diff --git a/.github/workflows/tests/call-analyzer/spec/sentence.nlp b/.github/workflows/tests/call-analyzer/spec/sentence.nlp new file mode 100644 index 00000000..613c02e2 --- /dev/null +++ b/.github/workflows/tests/call-analyzer/spec/sentence.nlp @@ -0,0 +1,7 @@ +############################################### +# FILE: sentence.nlp +# SUBJ: Group each sentence, so the next pass has a node to hand over. +############################################### + +@RULES +_sent <- _xALPHA _xWILD [star fails=(\.)] \. @@ diff --git a/cs/libconsh/cg.cpp b/cs/libconsh/cg.cpp index 696afa5c..9bbe5620 100644 --- a/cs/libconsh/cg.cpp +++ b/cs/libconsh/cg.cpp @@ -4597,6 +4597,10 @@ bool CG::openFullKBB(const std::string &file) std::_t_cerr << _T("[Lazy-loading words from ") << file << _T(" under \"") << rootName << _T("\"]") << std::endl; + + // A word missed before this file was open may be in it. Only matters when + // files are added mid-run, as callanalyzer() does. // 09/13/26 DD. + fullMissCache_.clear(); return true; } @@ -4625,6 +4629,9 @@ bool CG::openFullDict(const std::string &file) } std::_t_cerr << _T("[Lazy-loading words from ") << file << _T("]") << std::endl; + + // See openFullKBB. // 09/13/26 DD. + fullMissCache_.clear(); return true; } diff --git a/include/Api/lite/Arun.h b/include/Api/lite/Arun.h index 0d1c8e13..33020072 100644 --- a/include/Api/lite/Arun.h +++ b/include/Api/lite/Arun.h @@ -1737,6 +1737,13 @@ class LITE_API Arun static bool findana(Nlppp*,RFASem*); // 05/29/03 AM. static bool findana(Nlppp*,long long); // 07/11/03 AM. + // In callana.cpp. // 09/13/26 DD. + static long long callanalyzer(Nlppp*,NODE*,RFASem*,_TCHAR*); + static long long callanalyzer(Nlppp*,NODE*,RFASem*,RFASem*); + static long long callanalyzer(Nlppp*,RFASem*,RFASem*,_TCHAR*); + static long long callanalyzer(Nlppp*,RFASem*,RFASem*,RFASem*); + static RFASem *callconcept(Nlppp*); + static bool inputrangetofile(Nlppp*,long long,long long,std::_t_ostream*); // 05/29/03 AM. static bool inputrangetofile(Nlppp*,long long,long long,RFASem*); static bool inputrangetofile(Nlppp*,long long,RFASem*,std::_t_ostream*); diff --git a/include/Api/lite/nlpdebug.h b/include/Api/lite/nlpdebug.h index 4cc0e257..064cb493 100644 --- a/include/Api/lite/nlpdebug.h +++ b/include/Api/lite/nlpdebug.h @@ -76,6 +76,14 @@ class LITE_API NlpDebug static void arm(); static void disarm(); + // Hold the pause points off while the engine runs something other than the + // analyzer being debugged, including across the arm() of a nested analysis. + // callanalyzer() needs this: the called analyzer's pass numbers and lines + // would otherwise be reported against the caller's files. Calls nest. + // suspend() returns whether the points were armed, for the matching resume(). + static bool suspend(); + static void resume(bool wasArmed); + // True once a client is attached. Read directly by the inline hooks below; // public so they can stay inline. static bool active_; diff --git a/lite/callana.cpp b/lite/callana.cpp new file mode 100644 index 00000000..fd531da8 --- /dev/null +++ b/lite/callana.cpp @@ -0,0 +1,558 @@ +/******************************************************************************* +Copyright (c) 2026 by Text Analysis International, Inc. +All rights reserved. +*******************************************************************************/ +// callana.cpp +// +// callanalyzer() and callconcept(): one analyzer's passes run inside another's. +// +// WHAT IT DOES. callanalyzer(pnode, concept, "name") runs the passes of the +// named analyzer inside the analysis already in progress. The called analyzer +// gets no text or tree of its own. Its passes work on the subtree under pnode +// in the caller's parse tree, and on the caller's KB, where callconcept() gives +// them the concept they were handed to put things in. Whatever they change is +// there for the caller as soon as the call returns. +// +// WHAT IS LOADED ONCE. The first call builds the analyzer's passes (its rules +// and @DECL functions) and reads its kb/user .kbb and .dict files into the +// caller's KB. Its lazily loaded *full.kbb and *full.dict files are registered +// with that KB. The analyzer then stays in the VTRun registry, so no later call +// reads anything again. Its .kb files are not read: they are a whole saved KB, +// hierarchy and all, and reading one into a KB that already has a hierarchy +// adds its attribute values a second time. +// +// WHAT RUNS ON EACH CALL. The passes, in order, on the subtree, with these +// differences from running on a text of its own: +// - tokenizer passes are skipped, because the tree already exists; +// - a dicttok or dicttokz pass looks up the subtree's words instead, +// including in the lazy *full files, which only load a word once it is +// seen; +// - G() variables start empty and are discarded afterwards; +// - G("$apppath") is the called analyzer's folder; +// - no per-pass .tree dumps, which are named by pass number and would +// overwrite the caller's. +// +// WHAT IS REFUSED. An analyzer cannot call itself, directly or around a cycle +// (A calls B calls A). Its passes are a single set of objects, and they hold +// state while they run. + +#include "StdAfx.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "machine.h" +#include "lite/lite.h" +#include "lite/global.h" +#include "u_out.h" +#include "consh/libconsh.h" +#include "consh/cg.h" +#include "htab.h" +#include "kb.h" +#include "prim/libprim.h" +#include "lite/mach.h" +#include "dlist.h" +#include "node.h" +#include "tree.h" +#include "lite/Auser.h" +#include "lite/iarg.h" +#include "inline.h" +#include "str.h" +#include "chars.h" +#include "io.h" +#include "pn.h" +#include "ana.h" +#include "parse.h" +#include "Eana.h" +#include "lite/nlp.h" +#include "lite/nlppp.h" +#include "rfasem.h" +#include "arg.h" +#include "ipair.h" +#include "seqn.h" +#include "algo.h" +#include "dicttok.h" +#include "lite/vtrun.h" +#include "lite/nlpdebug.h" +#include "lite/Arun.h" +#include "fn.h" + +// What callconcept() returns when the analyzer is not being called: somewhere +// to put results while developing it on its own. +static _TCHAR STANDALONE_CONCEPT[] = _T("callanalyzer"); + +// One callanalyzer() in progress. +struct Call + { + Ana *caller; // The analyzer that made the call. + Ana *callee; // The analyzer whose passes are running. + CONCEPT *con; // What callconcept() returns to them. + }; + +// Calls in progress, outermost first. +static std::vector calls; + +// Each loaded analyzer paired with a KB its files have been read into. +static std::set > loadedInto; + +// Paths handed to the analyzers loaded here. The engine passes these around as +// bare pointers, so keep them for the life of the process rather than rely on +// every holder having made a copy. A list, so the strings never move. +static std::list anaPaths; + +static bool callError(Parse *parse, const std::string &msg) +{ +_stprintf(Errbuf, _T("[callanalyzer: %.*s]"), (int)(MAXSTR - 20), msg.c_str()); +parse->errOut(true); +return false; +} + +static bool isAbsolute(const std::string &path) +{ +if (path.empty()) + return false; +if (path[0] == '/' || path[0] == '\\') + return true; +return path.size() > 1 && path[1] == ':'; +} + +static std::string trimSlashes(std::string path) +{ +while (path.size() > 1 && (path.back() == '/' || path.back() == '\\')) + path.pop_back(); +return path; +} + +static std::string baseName(const std::string &path) +{ +size_t slash = path.find_last_of("/\\"); +return slash == std::string::npos ? path : path.substr(slash + 1); +} + +static std::string dirName(const std::string &path) +{ +size_t slash = path.find_last_of("/\\"); +return slash == std::string::npos ? std::string(".") : path.substr(0, slash); +} + +static _TCHAR *keepPath(const std::string &path) +{ +anaPaths.push_back(path); +return (_TCHAR *) anaPaths.back().c_str(); +} + +// Passes that build the parse tree from the text. +static bool isTokenizer(_TCHAR *algo) +{ +return algo + && (!strcmp_i(algo, _T("tokenize")) + || !strcmp_i(algo, _T("tok")) + || !strcmp_i(algo, _T("token")) + || !strcmp_i(algo, _T("cmltokenize")) + || !strcmp_i(algo, _T("cmltok")) + || !strcmp_i(algo, _T("chartok")) + || !strcmp_i(algo, _T("lines")) + || !strcmp_i(algo, _T("line"))); +} + +static bool isDictTok(_TCHAR *algo) +{ +return algo + && (!strcmp_i(algo, _T("dicttok")) + || !strcmp_i(algo, _T("dicttokz"))); +} + +/******************************************** +* FN: FINDCALLEE +* SUBJ: Find the named analyzer, building its passes on first use. +* NOTE: A name already in the registry is used as is -- that is what +* makes the second call free. Otherwise an absolute path names +* the analyzer folder, and anything else is looked for beside the +* calling analyzer's folder, which is how analyzers sit in a +* VisualText workspace. +********************************************/ + +static NLP *findCallee(Parse *parse, const std::string &given) +{ +VTRun *vtrun = parse->getNLP()->getVTRun(); + +std::string path = trimSlashes(given); +std::string name = baseName(path); +NLP *nlp = vtrun->findAna((_TCHAR *) name.c_str()); +if (nlp) + return nlp; + +std::string anadir = isAbsolute(path) + ? path + : dirName(trimSlashes(parse->getAppdir())) + DIR_STR + path; +std::string seqfile = anadir + DIR_STR + "spec" + DIR_STR + "analyzer.seq"; +if (!std::ifstream(seqfile.c_str()).good()) + { + callError(parse, "No analyzer named " + given + ": there is no " + seqfile + "."); + return 0; + } + +_TCHAR *dir = keepPath(anadir); +bool silent = parse->getEana()->getFsilent(); +clock_t start = clock(); + +// The same steps as NLP_ENGINE::init, which cannot be used from inside a run: +// it resets the engine's notion of the current analyzer. The analyzer gets a +// KB object because an NLP expects one, but it is never read -- its passes run +// on the caller's KB. +nlp = vtrun->makeNLP(dir, (_TCHAR *) name.c_str(), false, silent, false); +if (!nlp) + { + callError(parse, "Couldn't create analyzer " + name + "."); + return 0; + } +if (!vtrun->makeCG(dir, false, nlp, true)) + { + vtrun->rmAna(nlp); + vtrun->deleteNLP(nlp); + callError(parse, "Couldn't make a knowledge base object for " + name + "."); + return 0; + } +if (!nlp->make_analyzer(keepPath(seqfile), dir, false, silent, 0, false, false)) + { + vtrun->rmAna(nlp); + vtrun->deleteNLP(nlp); + callError(parse, "Couldn't build analyzer " + name + ". See its logs" + + DIR_STR + "make_ana.log."); + return 0; + } + +if (!silent) + std::_t_cerr << _T("[callanalyzer: loaded ") << name.c_str() << _T(": ") + << (double)(clock() - start) / CLOCKS_PER_SEC << _T(" sec]") << std::endl; +return nlp; +} + +// The called analyzer's kb/user files of one kind, as CG::openKBB and +// CG::openDict choose them: a consolidated all. if there is one, else +// every file with that extension. +static std::vector kbFiles( + const std::filesystem::path &kbdir, const std::string &ext) +{ +std::vector files; +std::error_code ec; +std::filesystem::path all = kbdir / ("all" + ext); +if (std::filesystem::exists(all, ec)) + { + files.push_back(all); + return files; + } +for (const auto &entry : std::filesystem::directory_iterator(kbdir, ec)) + if (entry.path().extension().string() == ext) + files.push_back(entry.path()); +std::sort(files.begin(), files.end()); +return files; +} + +// Read the called analyzer's dictionaries and kbb files into the KB it is +// run with, once for each such KB. Lazy *full files are registered, not read. +static void loadKnowledge(NLP *callee, Ana *ana, CG *cg) +{ +if (!loadedInto.insert(std::make_pair(callee, cg)).second) + return; + +std::error_code ec; +std::filesystem::path kbdir = std::filesystem::path(ana->getAppdir()) / "kb" / "user"; +if (!std::filesystem::is_directory(kbdir, ec)) + return; + +// kbb files first, as CG::readKB reads them, so dictionaries can pair with them. +std::vector kbbs = kbFiles(kbdir, ".kbb"); +std::vector dicts = kbFiles(kbdir, ".dict"); +for (const auto &file : kbbs) + { + if (cg->stemEndsWithFull(file.stem().string())) + cg->openFullKBB(file.string()); + else + cg->readKBB(file.string()); + } +for (const auto &file : dicts) + { + if (cg->stemEndsWithFull(file.stem().string())) + cg->openFullDict(file.string()); + else + cg->readDict(file.string(), kbbs); + } +} + +// Run a loaded analyzer's passes on the subtree under node. +static bool runCallee(Parse *parse, NLP *callee, Node *node, CONCEPT *con) +{ +Ana *ana = (Ana *) callee->getAna(); +if (!ana || !ana->getSeq()) + return callError(parse, std::string(callee->getName()) + " has no passes."); + +Ana *caller = parse->getAna(); +CG *cg = caller->getCG(); +loadKnowledge(callee, ana, cg); + +// Passes find the KB, and their @DECL functions, through the Ana the parse is +// running, so the called analyzer's Ana is put in and pointed at this KB. +CG *ownCG = ana->getCG(); +ana->setCG(cg); + +TREE *tree = parse->getTree(); +Delt *seq = parse->getSeq(); +long currpass = parse->getCurrpass(); +long rulepass = parse->getRulepass(); +Dlist *vars = parse->getVars(); +std::string appdir = parse->getAppdir(); + +Tree subtree(node); // Does not own the nodes. +parse->setTree(&subtree); +parse->setAna(ana); +parse->setVars(0); +parse->setAppdir(ana->getAppdir()); + +Call call = { caller, ana, con }; +calls.push_back(call); + +bool ok = true; +long num = 0; +for (Delt *step = ana->getSeq(); step && ok; step = step->Right()) + { + ++num; + Seqn *pass = step->getData(); + Algo *algo = pass->getAlgo(); + _TCHAR *algoname = pass->getAlgoname(); + if (!pass->getActive() || !algo || isTokenizer(algoname)) + continue; + + // What Parse::stepExecute and iniPass set, minus the dump files. + parse->setSeq(step); + parse->setCurrpass(num); + parse->setRulepass(num); + if (isDictTok(algoname)) + ((DICTTok *) algo)->applyToSubtree(parse, node); + else + ok = algo->Execute(parse, pass); + } + +calls.pop_back(); + +if (parse->getVars()) + Dlist::DeleteDlistAndData(parse->getVars()); +parse->setVars(vars); +parse->setAppdir((_TCHAR *) appdir.c_str()); +parse->setAna(caller); +parse->setTree(tree); +parse->setSeq(seq); +parse->setCurrpass(currpass); +parse->setRulepass(rulepass); +ana->setCG(ownCG); + +if (!ok) + return callError(parse, std::string("A pass of ") + callee->getName() + " failed."); +return true; +} + +static bool callAnalyzer(Parse *parse, Node *node, CONCEPT *con, _TCHAR *given) +{ +if (!node || !con) + return callError(parse, "Given no parse node or no concept."); +if (!given || !*given) + return callError(parse, "Given no analyzer name."); + +// Nothing the called analyzer does -- building from its rule files, or running +// its passes -- is the analyzer being debugged. Its pass numbers and lines +// would be reported against the caller's files. +bool wasArmed = NlpDebug::suspend(); + +bool ok = false; +NLP *callee = findCallee(parse, given); +if (callee) + { + Ana *ana = (Ana *) callee->getAna(); + bool running = (ana == parse->getAna()); + for (const Call &call : calls) + if (call.caller == ana || call.callee == ana) + running = true; + if (running) + callError(parse, std::string(callee->getName()) + " is already running." + + " An analyzer cannot call itself, directly or through another analyzer."); + else + ok = runCallee(parse, callee, node, con); + } + +NlpDebug::resume(wasArmed); +return ok; +} + +static CONCEPT *callConcept(Parse *parse) +{ +if (!calls.empty()) + return calls.back().con; +CG *cg = parse->getAna()->getCG(); +CONCEPT *root = cg->findRoot(); +return root ? cg->getConcept(root, STANDALONE_CONCEPT) : 0; +} + + +/******************************************** +* FN: FNCALLANALYZER +* CR: 09/13/26 DD. +* SUBJ: Run another analyzer's passes on part of this parse tree. +* RET: True if ok, else false. +* UP - 1 if the analyzer ran, else 0. +* FORMS: callanalyzer(pnode, concept, analyzer_str) +* NOTE: The analyzer works on the subtree under pnode and on this KB, +* and callconcept() gives it the concept. It is loaded on first use +* and stays loaded. +********************************************/ + +bool Fn::fnCallanalyzer( + Delt *args, + Nlppp *nlppp, + /*UP*/ + RFASem* &sem + ) +{ +sem = 0; +Parse *parse = nlppp->parse_; + +RFASem *node_sem = 0; +RFASem *con_sem = 0; +_TCHAR *name = 0; + +if (!Arg::sem1(_T("callanalyzer"),nlppp,(DELTS*&)args,node_sem)) + return false; +if (!Arg::sem1(_T("callanalyzer"),nlppp,(DELTS*&)args,con_sem)) + return false; +if (!Arg::str1(_T("callanalyzer"),(DELTS*&)args,name)) + return false; +if (!Arg::done((DELTS*)args,_T("callanalyzer"),parse)) + return false; + +Node *node = (node_sem && node_sem->getType() == RSNODE) + ? node_sem->getNode() : 0; +CONCEPT *con = (con_sem && con_sem->getType() == RS_KBCONCEPT) + ? con_sem->getKBconcept() : 0; + +sem = new RFASem(callAnalyzer(parse, node, con, name) ? 1LL : 0LL); +return true; +} + + +/******************************************** +* FN: FNCALLCONCEPT +* CR: 09/13/26 DD. +* SUBJ: The concept an analyzer was handed by callanalyzer(). +* RET: True if ok, else false. +* UP - the concept. +* FORMS: callconcept() +* NOTE: Run on its own, the analyzer gets the concept "callanalyzer" +* under the KB root instead, so it can be developed without a +* caller. +********************************************/ + +bool Fn::fnCallconcept( + Delt *args, + Nlppp *nlppp, + /*UP*/ + RFASem* &sem + ) +{ +sem = 0; +Parse *parse = nlppp->parse_; +if (!Arg::done((DELTS*)args,_T("callconcept"),parse)) + return false; + +CONCEPT *con = callConcept(parse); +if (con) + sem = new RFASem(con, RS_KBCONCEPT, parse->getAna()->getCG()); +return true; +} + + +/******************************************** +* FN: CALLANALYZER +* CR: 09/13/26 DD. +* SUBJ: Compiled-analyzer form of callanalyzer(). +********************************************/ + +long long Arun::callanalyzer( + Nlppp *nlppp, + NODE *node, + RFASem *con_sem, + _TCHAR *name + ) +{ +CONCEPT *con = 0; +if (con_sem) + { + if (con_sem->getType() == RS_KBCONCEPT) + con = con_sem->getKBconcept(); + delete con_sem; + } +return callAnalyzer(nlppp->parse_, (Node *) node, con, name) ? 1 : 0; +} + +// VARIANT. +long long Arun::callanalyzer( + Nlppp *nlppp, + NODE *node, + RFASem *con_sem, + RFASem *name_sem + ) +{ +_TCHAR *name = name_sem ? sem_to_str(name_sem) : 0; +long long ok = callanalyzer(nlppp, node, con_sem, name); +if (name_sem) + delete name_sem; +return ok; +} + +// VARIANT. +long long Arun::callanalyzer( + Nlppp *nlppp, + RFASem *node_sem, + RFASem *con_sem, + _TCHAR *name + ) +{ +NODE *node = node_sem ? node_sem->sem_to_node() : 0; +if (node_sem) + delete node_sem; +return callanalyzer(nlppp, node, con_sem, name); +} + +// VARIANT. +long long Arun::callanalyzer( + Nlppp *nlppp, + RFASem *node_sem, + RFASem *con_sem, + RFASem *name_sem + ) +{ +NODE *node = node_sem ? node_sem->sem_to_node() : 0; +if (node_sem) + delete node_sem; +return callanalyzer(nlppp, node, con_sem, name_sem); +} + + +/******************************************** +* FN: CALLCONCEPT +* CR: 09/13/26 DD. +* SUBJ: Compiled-analyzer form of callconcept(). +********************************************/ + +RFASem *Arun::callconcept( + Nlppp *nlppp + ) +{ +Parse *parse = nlppp->parse_; +CONCEPT *con = callConcept(parse); +return con ? new RFASem(con, RS_KBCONCEPT, parse->getAna()->getCG()) : 0; +} diff --git a/lite/dicttok.cpp b/lite/dicttok.cpp index d0419395..59eddf67 100644 --- a/lite/dicttok.cpp +++ b/lite/dicttok.cpp @@ -336,6 +336,60 @@ bool DICTTok::ApplyDictFiles() { return true; } +/******************************************** +* FN: APPLYTOSUBTREE +* CR: 09/13/26 DD. +* SUBJ: Run this pass's dictionary step on part of an existing tree. +* NOTE: For an analyzer run by callanalyzer(), which works on a node of +* its caller's tree and must not rebuild it. Every token under top +* is looked up -- lazily loaded *full dictionaries included -- and +* given its dictionary attributes, then multi-word dictionary +* phrases are matched among top's children. +********************************************/ + +bool DICTTok::applyToSubtree(Parse *parse, Node *top) +{ +if (!parse || !top) + return false; + +parse_ = parse; +cg_ = parse->getAna()->getCG(); +htab_ = parse->htab_; +Tree subtree(top); // Does not own the nodes. +tree_ = &subtree; +root_ = top; + +lookupTokens(top->Down()); +ApplyDictFiles(); + +tree_ = 0; +root_ = 0; +return true; +} + +// Give every token in a list of nodes, and beneath them, its dictionary +// attributes. +void DICTTok::lookupTokens(Node *node) +{ +_TCHAR buf[PATHSIZ]; +for (; node; node = node->Right()) + { + Pn *pn = node->getData(); + if (pn->getType() == PNNODE) + { + lookupTokens(node->Down()); + continue; + } + _TCHAR *name = pn->getName(); + if (pn->getType() == PNWHITE || !name || !*name) + continue; + CONCEPT *con = cg_->findWordConcept(name); + if (!con) + con = cg_->findWordConcept(str_to_lower(name, buf)); + findAttrs(node, con, name, false); + } +} + Node* DICTTok::MatchLongest(CONCEPT *con, Node *parentN, CONCEPT **end, int &length, int level) { _TCHAR conName[MAXSTR]; CONCEPT *next = con; diff --git a/lite/dicttok.h b/lite/dicttok.h index b31a650d..af65862a 100644 --- a/lite/dicttok.h +++ b/lite/dicttok.h @@ -51,6 +51,8 @@ class DICTTok : public Algo bool Execute(Parse *, Seqn *); // Perform the tokenization. bool Tokenize(Parse *); // Perform the tokenization. bool ApplyDictFiles(); + bool applyToSubtree(Parse *, Node *); // For callanalyzer(). // 09/13/26 DD. + void lookupTokens(Node *); // 09/13/26 DD. Node* MatchLongest(CONCEPT *con, Node *parentN, CONCEPT **end, int &length, int level); bool copyAttrsToSuggested(Pn *pn, Node *suggestedPn, Node *endNode); bool checkCase(_TCHAR *name, Node *node, bool &lower, bool &cap, bool &upper); diff --git a/lite/fn.cpp b/lite/fn.cpp index 5564cf94..0cd49dbb 100644 --- a/lite/fn.cpp +++ b/lite/fn.cpp @@ -455,6 +455,10 @@ switch (fnid) // 12/21/01 AM. return fnJsonwrite(args,nlppp,/*UP*/sem); // 08/04/26 DD. case FNjsonparse: return fnJsonparse(args,nlppp,/*UP*/sem); // 08/04/26 DD. + case FNcallanalyzer: // In callana.cpp. + return fnCallanalyzer(args,nlppp,/*UP*/sem); // 09/13/26 DD. + case FNcallconcept: // In callana.cpp. + return fnCallconcept(args,nlppp,/*UP*/sem); // 09/13/26 DD. case FNlogten: return fnLogten(args,nlppp,/*UP*/sem); // 04/29/04 AM. case FNrandomint: diff --git a/lite/fn.h b/lite/fn.h index 9839cff0..1b320151 100644 --- a/lite/fn.h +++ b/lite/fn.h @@ -979,6 +979,8 @@ static bool fnStruniquechars( static bool fnPush(Delt*,Nlppp*,RFASem*&); // 08/03/26 DD. static bool fnJsonwrite(Delt*,Nlppp*,RFASem*&); // 08/04/26 DD. static bool fnJsonparse(Delt*,Nlppp*,RFASem*&); // 08/04/26 DD. + static bool fnCallanalyzer(Delt*,Nlppp*,RFASem*&); // 09/13/26 DD. + static bool fnCallconcept(Delt*,Nlppp*,RFASem*&); // 09/13/26 DD. static bool fnStriscaps(Delt*,Nlppp*,RFASem*&); static bool fnStrisupper(Delt*,Nlppp*,RFASem*&); // 11/20/01 AM. static bool fnStrislower(Delt*,Nlppp*,RFASem*&); // 11/20/01 AM. diff --git a/lite/func_defs.h b/lite/func_defs.h index 6f25784f..312e620c 100644 --- a/lite/func_defs.h +++ b/lite/func_defs.h @@ -397,6 +397,10 @@ enum funcDef FNjsonwrite, FNjsonparse, + // Analyzer functions. // 09/13/26 DD. + FNcallanalyzer, + FNcallconcept, + FNXXYYZZ }; #endif diff --git a/lite/funcs.h b/lite/funcs.h index 5edeed2b..abd5cbf4 100644 --- a/lite/funcs.h +++ b/lite/funcs.h @@ -386,6 +386,9 @@ _T("push"), // JSON functions. // 08/04/26 DD. _T("jsonwrite"), _T("jsonparse"), +// Analyzer functions. // 09/13/26 DD. +_T("callanalyzer"), +_T("callconcept"), 0 }; #endif // NLP_LITE_FUNCS_H diff --git a/lite/nlpdebug.cpp b/lite/nlpdebug.cpp index 538d5263..b6f93a99 100644 --- a/lite/nlpdebug.cpp +++ b/lite/nlpdebug.cpp @@ -1124,8 +1124,12 @@ void NlpDebug::ruleFailed_(Nlppp *nlppp) stopAndServe(NLPDEBUG_RULE_FAILED); } +// How many suspend() calls are in effect. arm() does nothing while nonzero. +static int g_suspended = 0; + void NlpDebug::arm() { + if (g_suspended) return; g_armed = true; } @@ -1134,6 +1138,20 @@ void NlpDebug::disarm() g_armed = false; } +bool NlpDebug::suspend() +{ + bool wasArmed = g_armed; + ++g_suspended; + g_armed = false; + return wasArmed; +} + +void NlpDebug::resume(bool wasArmed) +{ + if (g_suspended > 0 && --g_suspended == 0) + g_armed = wasArmed; +} + void NlpDebug::statement_(Nlppp *nlppp, long line) { if (!g_armed) return; diff --git a/nlp/main.cpp b/nlp/main.cpp index 403d4c8a..615bbac4 100644 --- a/nlp/main.cpp +++ b/nlp/main.cpp @@ -15,7 +15,7 @@ All rights reserved. #include "lite/nlp_engine.h" #include "version.h" -#define NLP_ENGINE_VERSION "4.0.0" +#define NLP_ENGINE_VERSION "4.1.0" bool cmdReadArgs(int, _TCHAR *argv[], _TCHAR *&, _TCHAR *&, _TCHAR *&, _TCHAR *&, bool &, bool &, bool &, bool &, bool &, bool &, int &); void cmdHelpargs(_TCHAR *);