% Copyright 2012-2022, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation, either version 3 of the License, or % (at your option) any later version. % % SPLinT is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU General Public License for more details. % % You should have received a copy of the GNU General Public License % along with SPLinT. If not, see . % tree evaluator macros. % #1: first token of a leaf \def\leafexpand#1{% \ifcat\noexpand#1\relax % the leaf starts with an expandable token or control sequence \xskiptofi{\expandafter\leafexpand}% \else \xskiptofi{\leafattach}% \fi #1% } % #1: the leaf % #2: {{pruned tree}{last pruned branch}} \def\leafattach#1\endleaf#2{% \leafatt@ch{#1}#2% } % #1: the leaf % #2: pruned tree % #3: last pruned branch \def\leafatt@ch#1#2#3{% \leaf@tt@ch{#1}{#2}#3% } \def\xname{\expandafter\eatone\string} % #1: the leaf % #2: pruned tree % #3: treenode type \def\leaf@tt@ch#1#2#3{% \csname\xname#3.ifargdone\endcsname % all leaves of the last pruned node have been evaluated, evaluate the node \xskiptofi{\csname leafprune\csname\xname#3.arity\endcsname\endcsname{#2}#3{#1}}% \else % look at the next argument \xskiptofi{\csname nextargument\csname\xname#3.arity\endcsname\endcsname{#2}#3{#1}}% rest of the arguments follow \fi } % #1: pruned tree % #2: treenode type % #3: argument \expandafter\def\csname leafprune0\endcsname#1#2#3{% #3% } % #1: pruned tree % #2: treenode type % #3: argument \expandafter\def\csname leafprune1\endcsname#1#2#3{% \leafexpand#2{#3}\endleaf{#1}% } % #1: pruned tree % #2: treenode type % #3: argument1 % #4: argument2 \expandafter\def\csname leafprune2\endcsname#1#2#3#4{% \leafexpand#2{#3}{#4}\endleaf{#1}% } % #1: pruned tree % #2: treenode type % #3: argument1 \expandafter\def\csname nextargument1\endcsname#1#2#3{% \expandafter\expandafter\expandafter \treedesc@nd#3\endleaf{{#1}{#2}}% } % #1: pruned tree % #2: treenode type % #3: argument1 % #4: argument2 \expandafter\def\csname nextargument2\endcsname#1#2#3#4{% \expandafter\expandafter\expandafter \treedescend\csname\xname#2.argshift\endcsname{#4}{{#3}}{#1}% } % #1: treenode type % #2: last argument % #3: rest of arguments % #4: pruned tree \def\treedescend#1#2#3#4{% \treedesc@nd#2\endleaf{{#4}{#1#3}}% } % #1: treenode type or leaf \def\treedesc@nd#1{% \ifcat\noexpand#1\noexpand\relax % in case someone redefined \relax % this is an argument that has to be expanded \xskiptofi{\csname treed@sc@nd\csname\xname#1.arity\endcsname\endcsname}% \else % this is a leaf \xskiptofi{\leafattach}% \fi #1% } % data type, expand it \expandafter\def\csname treed@sc@nd0\endcsname{% \expandafter\leafattach % \leafattach will consume \endleaf } % unary operation % #1: treenode type % #2: argument1 % #3: pruned tree \expandafter\def\csname treed@sc@nd1\endcsname#1#2\endleaf#3{% \csname nextargument1\endcsname{#3}#1{#2}% } % binary operation % #1: treenode type % #2: argument1 % #3: argument2 % #4: pruned tree \expandafter\def\csname treed@sc@nd2\endcsname#1#2#3\endleaf#4{% \csname nextargument2\endcsname{#4}#1{#2}{#3}% } \def\treeeval#1{% \treeev@l#1% } \def\treeev@l#1{% \csname nextargument\csname\xname#1.arity\endcsname\endcsname{{}\xxttop}#1% } % #1: node name % #2: arity \def\nodesetup#1#2{% \expandafter\let\csname #1.ifargdone\endcsname\iftrue \ifnum#2>0 \expandafter\edef\csname #1.argshift\endcsname{% \expandafter\noexpand\csname #11\endcsname }% \fi \expandafter\edef\csname #1.arity\endcsname{#2}% \tempca\@ne \loop \ifnum\tempca<#2 \expandafter\def\csname #1\the\tempca.arity\endcsname{#2}% \makeargdonefalse{#1}% \tempcb\tempca \advance\tempca\@ne \ifnum\tempca<#2 \expandafter\edef\csname #1\the\tempcb.argshift\endcsname{% \expandafter\noexpand\csname #1\the\tempca\endcsname }% \else \expandafter\edef\csname #1\the\tempcb.argshift\endcsname{% \expandafter\noexpand\csname #1\endcsname }% \fi \repeat } \def\makeargdonefalse#1{\expandafter\let\csname #1\the\tempca.ifargdone\endcsname\iffalse}