Tag Archives: Pseudocode

Automaton Empyreum: the Key to Pygnition. (Trivial File Transfer Protocol edition.)

(I have implemented the Trivial File Transfer Protocol, revision 2, in this milestone snapshot. If you have dealt with reprogramming your home router, you may have encountered TFTP. Although other clients presently exist on Linux and elsewhere, I have implemented the protocol with a pair of Python scripts. You’ll need a Python interpreter, and possibly Administrator privileges (if the server requires them to open port 69), to run them. They can transfer files of size up to 32 Megabytes between any two computers communicating via UDP/IP. Warning: you may need to pull out your metaphorical monkey wrench and tweak the network timeout, or other parameters, in both the client and server before they work to your specification. You can also use TFTP to copy files on your local machine, if for whatever reason you need some replacement for the cp command. Links, courtesy of MediaFire, follow:

Executable source code (the programs themselves, ready to run on your computer): http://www.mediafire.com/file/rh5fmfq8xcmb54r/mlptk-2017-01-07.zip

Candy-colored source code (the pretty colors help me read, maybe they’ll help you too?): http://www.mediafire.com/file/llfacv6t61z67iz/mlptk-src-hilite-2017-01-07.zip

My life in a book (this is what YOUR book can look like, if you learn to use my automatic typesetter and tweak it to make it your own!): http://www.mediafire.com/file/ju972na22uljbtw/mlptk-book-2017-01-07.zip

)

Title is a tediously long pun on "Pan-Seared Programming" from the last lecture.
Key: mechanism to operate an electric circuit, as in a keyboard.
Emporium: ein handelsplatz; or, perhaps, the brain.
Empyreuma: the smell/taste of organic matter burnt in a close vessel (as, pans).
Lignite: intermediate between peat & bituminous coal. Empyreumatic odor.
Pignite: Pokémon from Black/White. Related to Emboar & Tepig (ember & tepid).
Pygmalion (Greek myth): a king; sculptor of Galatea, who Aphrodite animated.

A few more ideas that pop up often in the study of computer programming: which,
by the way, is not computer science. (Science isn't as much artifice as record-
keeping, and the records themselves are the artifact.)

MODULARITY
As Eric Steven Raymond of Thyrsus Enterprises writes in "The Art of Unix
Programming," "keep it simple, stupid." If you can take your programs apart, and
then put them back together like Lego(TM) blocks, you can craft reusable parts.

CLASSES
A kind of object with methods (functions) attached. These are an idiom that lets
you lump together all your program's logic with all of its data: then you can
take the class out of the program it's in, to put it in another one. _However,_
I have been writing occasionally for nearly twenty years (since I was thirteen)
and here's my advice: don't bother with classes unless you're preparing somewhat
for a team effort (in which case you're a "class" actor: the other programmers
are working on other classes, or methods you aren't), think your code would gain
from the encapsulation (perhaps you find it easier to read?), or figure there's
a burning need for a standardized interface to whatever you've written (unlikely
because you've probably written something to suit one of your immediate needs:
standards rarely evolve on their own from individual effort; they're written to
the specifications of consortia because one alone doesn't see what others need).
Just write your code however works, and save the labels and diagrams for some
time when you have time to doodle pictures in the margins of your notebook, or
when you _absolutely cannot_ comprehend the whole at once.

UNIONS
This is a kind of data structure in C. I bet you're thinking "oh, those fuddy-
duddy old C dinosaurs, they don't know what progress is really about!" Ah, but
you'll see this ancient relic time and again. Even if your language doesn't let
you handle the bytes themselves, you've got some sort of interface to them, and
even if you don't need to convert between an integer and four ASCII characters
with zero processing time, you'll still need to convert various data of course.
Classes then arise which simulate the behavior of unions, storing the same datum
in multiple different formats or converting back and forth between them.
(Cue the scene from _Jurassic Park,_ the film based on Michael Crichton's book,
 where the velociraptor peeks its head through the curtains at a half-scaffolded
 tourist resort. Those damn dinosaurs just don't know when to quit!)

ACTUALLY, VOID POINTERS WERE WHAT I WAS THINKING OF HERE
The most amusing use of void*s I've imagined is to implement the type definition
for parser tokens in a LALR parser. Suppose the parser is from a BNF grammar:
then the productions are functions receiving tokens as arguments and returning a
token. Of course nothing's stopping you from knowing their return types already,
but what if you want to (slow the algorithm down) add a layer of indirection to
wrap the subroutines, perhaps by routing everything via a vector table, and now
for whatever reason you actually _can't_ know the return types ahead of time?
Then of course you cast the return value of the function as whatever type fits.

ATOMICITY, OPERATOR OVERLOADING, TYPEDEF, AND WRAPPERS
Washing brights vs darks, convenience, convenience, & convenience, respectively.
Don't forget: convenience helps you later, _when_ you review your code.

LINKED LISTS
These are a treelike structure, or should I say a grasslike structure.
I covered binary trees at some length in my fourth post, titled "On Loggin'."

RECURSION
The reason why you need recursion is to execute depth-first searches, basically.
You want to get partway through the breadth of whatever you're doing at this
level of recursion, then set that stuff aside until you've dealt with something
immensely more important that you encountered partway through the breadth. Don't
confuse this with realtime operating systems (different than realtime priority)
or with interrupt handling, because depth-first searching is far different than
those other three topics (which each deserve lectures I don't plan to write).

REALTIME OPERATING SYSTEMS, REALTIME PRIORITY, INTERRUPT HANDLING
Jet airplanes, video games versus file indexing, & how not to save your sanity.

GENERATORS
A paradigm appearing in such pleasant languages as Python and Icon.
Generators are functions that yield, instead of return: they act "pause-able,"
and that is plausible because sometimes you really don't want to copy-and-paste
a block of code to compute intermediate values without losing execution context.
Generators are the breadth-first search to recursion's depth-first search, but
of course search algorithms aren't all these idioms are good for.
Suppose you wanted to iterate an N-ary counter over its permutations. (This is
similar to how you configure anagrams of a word, although those are combinations
-- for which, see itertools.combinations in the Python documentation, or any of
the texts on discrete mathematics that deal with combinatorics.) Now, an N-ary
counter looks a lot like this, but you probably don't want a bunch of these...
    var items = new Array(A, B, C, D, ...);       // ... tedious ...
    var L = items.length;                         // ... lines ...
    var nary = new Array(L);                      // ... of code ...
    for (var i = 0; i < L; nary[i++] = 0) ;       // ... cluttering ...
    for (var i = L - 1; i >= 0 && ++nary[i] == L; // ... all ...
        nary[i--] = ((i < 0) ? undefined : 0)     // ... your other ...
    ) ; // end for (incrementation)               // ... computations ...
... in the middle of some other code that's doing somewhat tangentially related.
So, you write a generator: it takes the N-ary counter by reference, then runs an
incrementation loop to update it as desired. The counter is incremented, where-
upon control returns to whatever you were doing in the first place. Voila!
(This might not seem important, but it is when your screen size is 80 by 24.)



NOODLES AND DOODLES, POMS ON YOUR POODLES, OODLES AND OODLES OF KITS & CABOODLES
(Boodle (v.t.): swindle, con, deceive. Boodle (n.): gimmick, device, strategy.)
Because this lecture consumed only about a half of the available ten thousand
characters permissible in a WordPress article, here's a PowerPoint-like summary
that I was doodling in the margins because I couldn't concentrate on real work.
Modularity: perhaps w/ especial ref to The Art of Unix Programming. "K.I.S.S."
Why modularity is important: take programs apart, put them together like legos.
Data structures: unions, classes.
Why structures are important: atomicity, op overloading, typedefs, wrappers.
linked lists: single, double, circular. Trees. Binary trees covered in wp04??
recursion: tree traversal, data aggregation, regular expressions -- "bookmarks"
Generators. Perhaps illustrate by reference to an N-ary counter?

AFTER-CLASS DISCUSSION WITH ONE HELL OF A GROUCHY ETHICS PROFESSOR
Suppose someone is in a coma and their standing directive requests you to play
some music for them at a certain time of day. How can you be sure the music is
not what is keeping them in a coma, or that they even like it at all? Having
experienced death firsthand, when I cut myself & bled with comical inefficiency,
I can tell you that only the dying was worth it. The pain was not, and I assure
you that my entire sensorium was painful for a while there -- even though I had
only a few small lacerations. Death was less unpleasant with less sensory input.
I even got sick of the lightbulb -- imagine that! I dragged myself out of the
lukewarm bathtub to switch the thing off, and then realized that I was probably
not going to die of exsanguination any time soon and went for a snack instead.

AFTER-CLASS DISCUSSION WITH ONE HELL OF A GROUCH
"You need help! You are insane!"
My 1,000 pages of analytical logic versus your plaintive bleat.
Advertisements

I will gladly pay you Tuesday for a Hnakkerbröd today.

Beware: when speaking to Trolls, listen carefully. It could save your ice hole.
        (Trolls are known for their skill in wintertime fishing.)

My software, courtesy of MediaFire:

https://www.mediafire.com/?ebbyj47e35mmytg (http://www.mediafire.com/download/ebbyj47e35mmytg/mlptk-qlupgradecomplete-awaitingspeedfix-27mar2016.zip)

This update (unlike the foregoing, which fixed the Opera bug) regards only QL.
Again: Quadrare Lexema is similar to GNU Bison. If an infringement, I'll delete
it as soon as I hear or see from you. BTW, Bison is time-tested; QL isn't.

Oh, and a correction to "First Rate?": Bison can indeed unshift multiple tokens
back onto its input stream, even though productions can't be multiple symbols in
length, by unshifting directly onto its input during reduction (which is how QL
does it too, during deferment, which amounts to the same exact thing because no
reason exists to compute anything during deferment -- otherwise, there'd be more
race conditions than the Kentucky Derby, which is very silly).

QL is now "kinda-sorta" debugged and functioning to my specification AFAICT. Now
the API has changed considerably from how it was last month (the argument vector
to reduction deferment class constructors has been modified, some new faculties
now exist, and some were removed); this necessitated additional instantiations
of "new Array()," and interolably reduces efficiency when operating on very long
inputs, but I wanted to hurry-up this design iteration. (That was one sentence.)

The token agglutination mechanism of the parser logic is the same as before.
Code to determine precedence & blocking has been abridged; toddling steps toward
a method to generate the parser as in-line code. (As you see, that isn't yet.)

I'm tempted to redo the infrastructure to reduce the number of new Array()s that
are instantiated during the parse phase, but I'm pretty sure I can do that by
rewriting the underlying code without changing the API. The interface between
the parser's stack extremum and its input stream is passed to reductions as an
Array(), but that doesn't mean it always has to be allocated anew.

Remember: the old Command Line Interpretation Translator scaffold isn't decided;
I left ::toTheLimit() where it was, pending a ::hatten() that shall suit you; if
you'd like to use the horrifying monstrosity that is my software architecture,
you can see Mr. Skeleton awaiting you in clit.js -- asking where is his flesh, &
rapidly becoming impatient with my poking and prodding him all day. Soon, Mr.
Skeleton; soon shall be the day when the hat is yours at last, & your calcareous
projection from within my library becomes a fully fledged automaton unto itself.

For the meantime I'm satisfied with the half-measure. I think the API is okay to
start building upon, so I'll start building. Overhaul of the back-end late this
year or early in the next, & it's looking good for me to furnish the CLIT before
the third quarter. Therefore I'd say: expect full CLIT functionality in 2016.

Before I apprise you of my progress so far, let's take a moment for a thoroughly
detailed technical analysis of Mr. Skeleton's bony protrusion.

Phoneme    <=    (EscapeSequence | AnyCharacter | Number | String)
                 (EscapeSequence | AnyCharacter | Number | String | Phoneme | )
	Concatenate a "word" that is one argument in an argument vector.

ISLDQ    <=    '\"'
	Open a <String>.

InchoateString    <=    (ISLDQ | InchoateString)
                        (OP_CAT | OP_CONJ | EscapeSequence | AnyCharacter
                         | Number | Space)
	Make strings out of any symbol following an open string.
	(As you can see, this rule must be rewritten...)

String    <=    InchoateString '\"'
	Close a <String>.

Argument    <=    Phoneme (Space | ) | Argument Argument
	Concatenate the argument vector comprising an executable MLPTK command.
	That bit with "(Space | )" should probably be just "Space".

Catenation    <=    (Argument | Group | Conjugation) OP_CAT
	Concatenate the output of commands.

MalformedGroupCohesion    <=    (Argument | Group | Conjugation) OP_CLPAR
	Automatically correct the user's malformed syntax where the last
	command in a parenthetical sub-grouping was not followed by a ";".

ExecutableInchoateConjugation    <=    Argument OP_CONJ | Blargument
	Signify that a command can be executed as part of a <Conjugation>.

InchoateConjugation    <=    Group OP_CONJ | Conjugation
	Convert a conjugated <Group>, or the output of a <Conjugation>,
	to an <InchoateConjugation> token that can form the left-hand
	part of a further <Conjugation>.
	This reduction causes parser stack differentiation, because it
	conflicts with "Catenation <= Conjugation OP_CAT".
	In that circumstance, the sequence "<Conjugation> <OP_CAT> ..."
	is both a "<Catenation> ..." and a "<InchoateConjugation> <OP_CAT> ...".
	Observe that the latter always produces a syntax error.
	I'm pretty sure I could rewrite the grammar of the <Conjugation> rule to
	fix this; IDK why I didn't. (Maybe a bug elsewhere makes it impossible.)

Conjugation    <=    (ExecutableInchoateConjugation | InchoateConjugation)
                     ExecutableInchoateConjugation
	Execute the command in the <ExecutableInchoateConjugation> at right,
	supplying on its standard input the standard output of that at left.

InchoateGroup    <=    (OP_OPPAR | InchoateGroup) Catenation
	Concatenate the contents of a parenthesized command sub-grouping.

Group    <=    InchoateGroup (OP_CLPAR | MalformedGroupCohesion)
	Close an <InchoateGroup>. Concatenate the contents of a
	<MalformedGroupCohesion> if it trailed.

CommandLine    <=    (CommandLine | ) Catenation
	Concatenate the output of <Catenation>s into one Array.
	This one actually doesn't differentiate. Either a <CommandLine> waits at
	left to consume a Catenation when it reduces, or something else does, &
	<Catenations> in mid-parse never reduce to <CommandLine>s except when
	fatal syntax errors occur, in which case the parser belches brimstone.
	
Blargument    <=    Argument (OP_CAT | OP_CLPAR)
    Duplicate the trailing concatenation operator or close parenthesis following
    an <Argument>, so that a <Conjugation> doesn't conflict with a <Catenation>
    or an <InchoateGroupCohesion>. I think this can be specified formally in a
    proper grammar, without the multiple-symbol unshift, but IDK how just yet --
    because (without lookahead) the parser can't know when the argument vector
    ends without seeing a trailing operator, so execution of the last command in
    the conjugation sequence <InchoateConjugation> <Argument> <OP_CAT> would
    occur when <Argument> <OP_CAT> reduces & executes, disregarding its standard
    input (the contents of the foregoing <InchoateConjugation>.
    "Blargument <= Argument" can never happen and "ExecutableInchoateConjugation
    <= Argument" would grab the <Argument> before it could concatenate with the
    next <Argument>, so I'm at a loss for how I should accomplish this formally.
    BTW, <Blargument> is the <WalkingBassline>, with trivial alterations.
    The <Blargument> reduction causes parser stack differentiation, because it
    conflicts with both <Catenation> and <MalformedGroupCohesion>. In either
    case, the <Blargument> branch encounters a syntax error & disappears
    when <Blargument> didn't immediately follow an inchoate conjugation; the
    other branch disappears in the inverse circumstance.

Token identifier   Operator precedence  Associativity
"Space", - - - - - 2, - - - - - - - - - "wrong",
"OP_CAT",  - - - - 0, - - - - - - - - - "wrong",
"EscapeSequence",  0, - - - - - - - - - "right",
"AnyCharacter",  - 0, - - - - - - - - - "right", (the sequence to the right of
"Number",  - - - - 0, - - - - - - - - - "right",  a right-associative token is
"String",  - - - - 0, - - - - - - - - - "right",  reduced first, except...)
"OP_OPPAR",  - - - 0, - - - - - - - - - "left",
"OP_CLPAR",  - - - 0, - - - - - - - - - "wrong", (... when wrong-associativity
"OP_CONJ", - - - - 0, - - - - - - - - - "wrong",  forces QL to reduce the right-
"QL_FINALIZE", - - 0, - - - - - - - - - "wrong"   associative sequence.)

The avid reader shall observe that my "wrong-associativity" specifier, when used
to define runs of right-associative tokens that stick to one another, is similar
to the lexical comparison & matching algorithm of a lexical analyzer (scanner).
In fact, as written, it _is_ a scanner. For an amusing diversion, try excerpting
the portions of the semantical analyzer (parser) that can be made into lexical
analyzer rules, then put them into the scanner; or wait a few months and I will.

But that's enough bony baloney.
If you preferred Mr. Skeleton as he was, see mlptk/old/clit.js.21mar2016.

As of probably a few days before I posted this brief, my upgrade to QL is now
sufficient to function vice its predecessor. I spruced-up Mr. Skeleton, so that
the test scaffold in clit.js now functions with ::hattenArDin() in QL, and now
everything looks all ready to go for shell arithmetic & such frills as that.

Ironically, it seems that I've made it slower by attempting to make it faster. I
 should have known better. I'll try to fix the speed problem soon; however,
until then, I've abandoned work on the Translator due to intolerable slowness.
I'm sorry for the inconvenience. If it's any help, I think the problem is due to
 too many new Array() invocations or too many nested Arrays, one of the two.
Either way, I intend to fix it this year by rewriting the whole parser (again)
as a static code generator.

I was also thinking of writing a windowing operating system for EmotoSys, but I
am uncertain how or whether to put clickable windows in the text console. I mean
-- it'd be simple now that QL's rolling, but maybe a more Spartan design? I will
post some flowcharts here when I've exhausted my ministrations to the CLIT.

Of Stack & State.

Next MLPTK development snapshot is available here, courtesy of Mediafire:
http://www.mediafire.com/download/476ynd7ee7cla07/mlptk-qlds16feb2016.zip
My manuscript describes some fascinating new ideas worth their weight in paper.
Parental discretion is advised, until I can excerpt the swearing and easter-egg.

This discourse follows the one I issued previously, which explained the theory
behind LALR parsers. Now I shall write of my library, Quadrare Lexema, which is
the work I've been engineering so that I can teach myself about that theory.

Beware that this algorithm is inefficient and a poor teaching example.
Also, because I have described it so briefly, this post is not yet a lecture.
As with the foregoing, it's public domain. So is my software.

A general-format parser (i.e.: a parser written to parse any grammar, as opposed
to parsers that are written by hand and whose grammar is fixed; or, in yet other
words, a soft-coded parser as opposed to a hard-coded one) must be capable of
reading a formal grammar. A formal grammar specifies how the input sequence is
to be agglutinated to produce semantic meaning via iterative computation of the
"phrases" encountered as the input is consumed. In an LR parser, this could be a
one-dimensional linked list or tree; or, if you're better at math than I, simply
a recursive function that generates the parser's static code as it reads rules.

I designed QL to generate a circularly-linked tree, in the hope I could rewrite
it to be more efficient later. The tree encodes, essentially, the conditional
expressions necessary for the parser to know which state it enters next when it
encounters a new input datum. In other words, "where do I go from here?" Later,
the tree is spidered by the parser, but that's another lecture. BTW, a spider is
a program that walks a path through {hyper,}linked data; i.e., spider = fractal.

QL reads a grammar that is very similar to Backus-Naur Format, or BNF, which is
the format read by GNU Bison. (For more information, consult the FSF or Wikipe.)
There are some non-deterministic extensions and other such frippery in my script
but the format of a grammar rule is mostly the same as BNF:
    - Symbol identifiers match a symbol w/ that ID at that position in sequence.
    - The "|", or OR operator, signifies either one symbol or another etc.
    - Parentheses are used to nest mutually exclusive ("OR"ed) subsequences.
    - Operator precedence and associativity is specified globally. (Non-BNF???)
The nonstandard extensions permit precedence and associativity to be specified
per-rule; arbitrary-length look{ahead,behind} assertions; & new specifiers for
operator precedence. Of these, only the new precedences are operational -- and
they both tend to break if not handled with nitroglycerine-quality caution.
There are a few other knobs and levers that change the behavior of the parser in
subtle ways, but these have naught to do with the state mapping phase.

Each grammar rule is specified as a duplet comprising a string (sequence of IDs)
and an object constructor (the reduction deferral object). The former element of
the duplet is significant to the state mapper; the latter, to the parser itself.

The rules are tokenized with a naive scanner; it changes non-operator, non-space
substrings to objects that represent nodes in the state map, passing the stream
of mixed tokens (nodes) & character literals (operators) to another method that
implements a "recursive" algorithm to attach each node to those succeeding it.
(It's a manual-transmission stack, but tantamount to recursion.) Succinctly:
    Beginning at locus zero, the root state whence all other states proceed,
    Either handle the operators:
    1. If this item of the token/operator stream is '(', increase stack depth.
    2. Else, if it's '|', the mediate (present) loci are stored @ terminal loci
       (that is, the "split ends" of the subsequence), & mediate loci cleared.
    3. Else if it's ')', decrease stack depth & the loci termini are catenated
       onto the mediate loci: i.e., the working loci now point at the nodes who
       signify each end of each branch in the foregoing parenthetical sequence.
    Otherwise,
    4. The identifier at this location in the rule string, which is a map node,
       is entered into the map at some index; this index is keyed (by the ID) in
       to the hash tables of all nodes corresponding to present loci.
    5. The new map entry becomes the new mediate locus. Or, possibly, an entry
       was entered separately for each present loci; in which case the new map
       entries become the new mediate loci.
    6. Proceed to next token in map path specification, or return mediate loci.
Note that the operators are less problematic when implemented w/ recursion; but,
because Javascript's maximum recursion in Firefox 3 is 3,000 calls, I didn't.

Here's an illustration of what the state map looks like:
                                | ROOT |
                               /   |   \
                     | NUMBER | | ABC | | XYZ |
                    /    |     \
               | + |   | - |  | * |  ... etc ...
              /     \    |      |
    | NUMBER | |STRING| |NUM| |NUM| ("NUM" is == NUMBER, but I ran out of space)
At each node, the sequence that's agglutinated by then can either reduce or not;
that, again, is the parser; I haven't space in this essay to explain it; however
I suffice to describe it thus.

I glossed-over the details to make the procedure more obvious. Again succinctly,
    - When the scanner produces map nodes, it also encodes some data in regard
      to lookahead/lookbehind predicates; and certain special-format identifiers
      such as "¿<anonymous Javascript function returning true or false>?" & ".",
      which I don't presently use and are either broken or unstable.
    - In transition between steps 4 and 5 above, if a node at some locus already
      has the map rule's identifier keyed in, the new path could be merged with
      the old one; in fact, it is, for now, but I'll change it later...
    - A backward link to the previous node, as well as the identifier of the
      eventual reduction of the sequence, is added in step 4.
    - Assorted other state data is added to the map retroactively: such as which
      tokens can block the parser and when; where an illegal reduction @ state 0
      can be made a node-skip elsewhere in the map; & so much other frippy stuff
      that I can't even remember and hope to revise out of the schematic.
      ("Frippy," cf. "Frippery," which is garish or cast-off finery.)
As you can see, the state mapper tries to do far too much.

Observe that the "manual-transmission stack," which I wrote by hand, encodes a
recursive algorithm that looks something like this in pseudocode:
    recursive function computeMapExpansion (Token_Stream) {
        declare variable Radices, to encode mutually exclusive subsets.
        // ("Radix" means "root;" here, the beginning of the tree subset.)

        declare variable Brooms, an array containing the "split ends" of the map
            subsequence that began at Radix.
        // (From "Witch's Broom," a crotch near the end of a tree branch.)

        for each token in Token_Stream {
            if the token is '(' {
                gather the parenthetical subsequence in some variable, eg Subseq

                duplet (SubRadices, SubBrooms) = computeMapExpansion(Subseq);

                attach each SubRadix as a next node after each current Broom.

                update Brooms (Brooms[current_brooms] = SubBrooms).
            } else, if the token is '|' {
                begin a new Radix and Brooms pair.
            } else {
                attach map node as next node following each current Broom,
                and update Brooms.
            }// end if-elif-else (parens operator? Mutex operator? Or map node?)
        } // end for (over token stream)

        return duplet containing Radices and Brooms;
    } // end function computeMapExpansion
Obviously that does the same thing, via the function invocation stack.

After the map is prepared, the parser uses it as a state configuration while it
reads input tokens. I plan to brief you on the parser in my next post.

Because some space is left, here are the relevant parts of quadrare-lexema.js:

    "addPath", function (atomized_rule, reduction_id) {
        // exactly the algorithm described above.
    },

    "_whither", function (present_state, next_symbol) {
        // essentially, "can the map node at <state> proceed to <next_symbol>?"
    },

    "reRefactor", function () {
        // call <refactor> for each illegal reduction removed from the root node
    },

    "refactor", function (reduction_id) {
        // essentially exactly the same algorithm as addPath; walks the tree to
        // factor the specified identifier out of any rules in which it appears.
    },

    "deriveTerminalsAndNon", function () {
        // separate which symbols are reductions, and which are from tokenizer.
    },

    "tellReductionTracks", function (initial_symbol_id) {
        // "if <initial_id> proceeds from state 0, to what does it reduce?"
    },

    "derivePotentialReductions", function (init_id) {
        // "what reductions could happen via compound reduction of sequence?"
    },

    "deriveAllPotentialReductions", function () {
        // "do that one up there a bunch of times."
    },

    "attachBlockingPredicates", function () {
        // "at any node in the map; if the parser must block here, and given the
        //  symbol that shall appear first in the sequence that begins when the
        //  parser blocks, can any potential reduction thence be shifted onto
        //  this sequence in progress which is blocking at this node?"
    },

    "StateNode", GenProtoTok(
        // metric tons of crap
    ),