/* c code generated by "tr/translate.c.pss" */ /* note: this c engine cannot handle unicode! */ #include #include #include #include #include "colours.h" #include "tapecell.h" #include "tape.h" #include "buffer.h" #include "charclass.h" #include "command.h" #include "parameter.h" #include "instruction.h" #include "labeltable.h" #include "program.h" #include "machine.h" #include "exitcode.h" #include "machine.methods.h" int main() { struct Machine machine; struct Machine * mm = &machine; newMachine(mm, stdin, 100, 10); // create a dummy newline so that doc structures work even // on the first line of the file/stream. add(mm, "nl*"); push(mm); script: while (!mm->peep != EOF) { if (mm->peep == EOF) { break; } else { readChar(mm); } /* read */ if (!workspaceInClassType(mm, "[:space:]")) { // count words per line with the accumulator mm->accumulator++; /* a+ */ while (!isspace(mm->peep) && readc(mm)) {} /* while */ put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "word*"); push(mm); goto parse; } // keep leading space in newline token? if (workspaceInClassType(mm, "[\n]")) { // set accumulator == 0 so that we can count words // per line (and know which is the first word) mm->accumulator = 0; /* zero */ mm->charsRead = 0; /* nochars */ while ((strchr(" ", mm->peep) != NULL) && readc(mm)) {} /* while */ put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "nl*"); push(mm); goto parse; } if (workspaceInClassType(mm, "[\r\t ]")) { mm->buffer.workspace[0] = '\0'; /* clear */ if (mm->peep != EOF) { continue; } } parse: // for debugging, add % as a latex comment. add(mm, "%%> line "); lines(mm); add(mm, " char "); chars(mm); add(mm, ": "); printf("%s", mm->buffer.workspace); /* print */ mm->buffer.workspace[0] = '\0'; /* clear */ while (pop(mm)) {} /* unstack */ printf("%s", mm->buffer.workspace); /* print */ while (push(mm)) {} /* stack */ add(mm, "\n"); printf("%s", mm->buffer.workspace); /* print */ mm->buffer.workspace[0] = '\0'; /* clear */ // ------------- // 1 token pop(mm); if (0 == strcmp(mm->buffer.workspace, "nl*")) { /* nop: eliminated */ } // here we classify words into other tokens // we can use accumulator with a+ a- to determine if current // word is the first word of the line, or even count number of // words per line. This should simplify grammar items such as // nl/--- and nl/star/ etc // another advantage, is that we can dispense with tokens such as // ---, >> etc and not have to get rid of them later. if (0 == strcmp(mm->buffer.workspace, "word*")) { mm->buffer.workspace[0] = '\0'; /* clear */ get(mm); // no numbers in headings! if (workspaceInClassType(mm, "[A-Z]")) { mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "uuword*"); push(mm); goto parse; } // at least three --- on a newline marks a code block start // use 'count;' here to simplify. The token --- probably doesnt // need to exist. if (strncmp(mm->buffer.workspace, "---", strlen("---")) == 0 && workspaceInClassType(mm, "[-]")) { mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "---*"); push(mm); goto parse; } // >> on a newline marks a code line start if (0 == strcmp(mm->buffer.workspace, ">>")) { add(mm, "*"); push(mm); goto parse; } // subheading marker if (strncmp(mm->buffer.workspace, "....", strlen("....")) == 0 && workspaceInClassType(mm, "[.]")) { mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "4dots*"); push(mm); goto parse; } // dash is used for lists // only make a dash token if it is first word on the line if (0 == strcmp(mm->buffer.workspace, "-")) { mm->buffer.workspace[0] = '\0'; /* clear */ count(mm); if (0 == strcmp(mm->buffer.workspace, "1")) { mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "dash*"); push(mm); goto parse; } mm->buffer.workspace[0] = '\0'; /* clear */ get(mm); } // ordered list start token // only make token if it is first word on the line if (0 == strcmp(mm->buffer.workspace, "o/-") || 0 == strcmp(mm->buffer.workspace, "O/-") || 0 == strcmp(mm->buffer.workspace, "0/-")) { mm->buffer.workspace[0] = '\0'; /* clear */ count(mm); if (0 == strcmp(mm->buffer.workspace, "1")) { mm->buffer.workspace[0] = '\0'; /* clear */ put(mm); add(mm, "olist*"); push(mm); goto parse; } mm->buffer.workspace[0] = '\0'; /* clear */ get(mm); } // unordered list start token if (0 == strcmp(mm->buffer.workspace, "u/-") || 0 == strcmp(mm->buffer.workspace, "U/-")) { mm->buffer.workspace[0] = '\0'; /* clear */ count(mm); if (0 == strcmp(mm->buffer.workspace, "1")) { mm->buffer.workspace[0] = '\0'; /* clear */ put(mm); add(mm, "ulist*"); push(mm); goto parse; } mm->buffer.workspace[0] = '\0'; /* clear */ get(mm); } // definition/description list start token // need to parse a bit differently because of the desc if (0 == strcmp(mm->buffer.workspace, "d/-") || 0 == strcmp(mm->buffer.workspace, "D/-")) { mm->buffer.workspace[0] = '\0'; /* clear */ count(mm); if (0 == strcmp(mm->buffer.workspace, "1")) { mm->buffer.workspace[0] = '\0'; /* clear */ // read description here, but have to escape special // verb cant go in here. Special chars will crash this. add(mm, "\n \\item["); while (!(strchr("\n:", mm->peep) != NULL) && readc(mm)) {} /* while */ add(mm, "]"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "dlist*"); push(mm); goto parse; } mm->buffer.workspace[0] = '\0'; /* clear */ get(mm); } // star on newline marks emphasis, list or code description // probably dont need star token. if (0 == strcmp(mm->buffer.workspace, "*")) { // check that * is 1st 'word' on line using accumulator mm->buffer.workspace[0] = '\0'; /* clear */ count(mm); if (0 != strcmp(mm->buffer.workspace, "1")) { mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "*"); } if (0 == strcmp(mm->buffer.workspace, "1")) { mm->buffer.workspace[0] = '\0'; /* clear */ while ((strchr(" \t\f", mm->peep) != NULL) && readc(mm)) {} /* while */ mm->buffer.workspace[0] = '\0'; /* clear */ while (!(strchr("\n", mm->peep) != NULL) && readc(mm)) {} /* while */ char *s = mm->buffer.workspace; /* cap */ if (*s) { *s = toupper((unsigned char) *s); s++; } while (*s) { *s = tolower((unsigned char) *s); s++; } put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ // this is a trick, because we want special LaTeX chars to // be escaped. So, will add \\emph{} after next replace code. add(mm, "::EMPH::"); get(mm); put(mm); //add "emline*"; push; .reparse } } // need to escape % # } \ and others // & % $ # _ { } ~ ^ \ // \textasciitilde, \textasciicircum, and \textbackslash replace(mm, "\\", "\\textbackslash "); /* replace */ replace(mm, "&", "\\&"); /* replace */ replace(mm, "%", "\\%"); /* replace */ replace(mm, "$", "\\$"); /* replace */ replace(mm, "#", "\\#"); /* replace */ replace(mm, "_", "\\_"); /* replace */ replace(mm, "{", "\\{"); /* replace */ replace(mm, "}", "\\}"); /* replace */ replace(mm, "~", "\\textasciitilde"); /* replace */ replace(mm, "^", "\\textasciicircum"); /* replace */ replace(mm, ">", "\\textgreater "); /* replace */ replace(mm, "<", "\\textless "); /* replace */ replace(mm, "LaTeX", "\\LaTeX{}"); /* replace */ // now make the emphasis line token, after special chars have // been escaped. if (strncmp(mm->buffer.workspace, "::EMPH::", strlen("::EMPH::")) == 0) { replace(mm, "::EMPH::", " \\emph{"); /* replace */ add(mm, "}"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "emline*"); push(mm); goto parse; } // If a previous test has matched, then the workspace should // be clear, and so none of the following will match. // graphical key representations if (strncmp(mm->buffer.workspace, "[", strlen("[")) == 0 && endsWith(mm->buffer.workspace, "]")) { replace(mm, "[esc]", "\\Esc"); /* replace */ replace(mm, "[enter]", "\\Enter"); /* replace */ replace(mm, "[return]", "\\Enter"); /* replace */ replace(mm, "[insert]", "\\Ins"); /* replace */ replace(mm, "[shift]", "\\Shift"); /* replace */ replace(mm, "[delete]", "\\Del"); /* replace */ replace(mm, "[home]", "\\Home"); /* replace */ // keys defined by 'keystroke' package, can make new ones. // \Enter \Del \Ins \Esc \Shift \Ctrl \Home // \End \PgUp \PgDown \PrtSc \Scroll \Break } //replace '\\n' "\\textbackslash n"; //replace '\\f' "\\textbackslash f"; //replace '\\r' "\\textbackslash r"; //replace '\\t' "\\textbackslash t"; put(mm); // urls, not so important for LaTex (and pdf) output. // Dont really need a token because we can render immediately // Could maybe render them as footnotes if (strncmp(mm->buffer.workspace, "http://", strlen("http://")) == 0 || strncmp(mm->buffer.workspace, "https://", strlen("https://")) == 0 || strncmp(mm->buffer.workspace, "www.", strlen("www.")) == 0 || strncmp(mm->buffer.workspace, "ftp://", strlen("ftp://")) == 0 || strncmp(mm->buffer.workspace, "sftp://", strlen("sftp://")) == 0) { // clear; add "url*"; push; .reparse // render as fixed pitch font mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "\\url{"); get(mm); add(mm, "}"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ } // format acronyms as a small capital font, case insensitive char *s = mm->buffer.workspace; /* lower */ while (*s) { *s = tolower((unsigned char) *s); s++; } if (0 == strcmp(mm->buffer.workspace, "antlr") || 0 == strcmp(mm->buffer.workspace, "pdf") || 0 == strcmp(mm->buffer.workspace, "json") || 0 == strcmp(mm->buffer.workspace, "ebnf") || 0 == strcmp(mm->buffer.workspace, "bnf") || 0 == strcmp(mm->buffer.workspace, "dns") || 0 == strcmp(mm->buffer.workspace, "html")) { mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "\\textsc{\\textbf{"); get(mm); add(mm, "}}"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ } // restore the mixed-case version of the input word if (0 != strcmp(mm->buffer.workspace, "")) { mm->buffer.workspace[0] = '\0'; /* clear */ get(mm); } // filenames, could be elided with quoted filenames if (0 == strcmp(mm->buffer.workspace, "parse>") || 0 == strcmp(mm->buffer.workspace, "print") || 0 == strcmp(mm->buffer.workspace, "pop") || 0 == strcmp(mm->buffer.workspace, "push") || 0 == strcmp(mm->buffer.workspace, "get") || 0 == strcmp(mm->buffer.workspace, "put") || 0 == strcmp(mm->buffer.workspace, ".reparse") || 0 == strcmp(mm->buffer.workspace, ".restart") || 0 == strcmp(mm->buffer.workspace, "add") || 0 == strcmp(mm->buffer.workspace, "sed") || 0 == strcmp(mm->buffer.workspace, "awk") || 0 == strcmp(mm->buffer.workspace, "grep") || 0 == strcmp(mm->buffer.workspace, "pep") || 0 == strcmp(mm->buffer.workspace, "nom") || 0 == strcmp(mm->buffer.workspace, "less") || 0 == strcmp(mm->buffer.workspace, "stdin") || 0 == strcmp(mm->buffer.workspace, "stdout") || 0 == strcmp(mm->buffer.workspace, "bash") || 0 == strcmp(mm->buffer.workspace, "lex") || 0 == strcmp(mm->buffer.workspace, "yacc") || 0 == strcmp(mm->buffer.workspace, "flex") || 0 == strcmp(mm->buffer.workspace, "bison") || 0 == strcmp(mm->buffer.workspace, "lalr") || 0 == strcmp(mm->buffer.workspace, "gnu") || endsWith(mm->buffer.workspace, ".h") || endsWith(mm->buffer.workspace, ".c") || endsWith(mm->buffer.workspace, ".a") || endsWith(mm->buffer.workspace, ".txt") || endsWith(mm->buffer.workspace, ".doc") || endsWith(mm->buffer.workspace, ".py") || endsWith(mm->buffer.workspace, ".rb") || endsWith(mm->buffer.workspace, ".rs") || endsWith(mm->buffer.workspace, ".java") || endsWith(mm->buffer.workspace, ".class") || endsWith(mm->buffer.workspace, ".tcl") || endsWith(mm->buffer.workspace, ".tk") || endsWith(mm->buffer.workspace, ".sw") || endsWith(mm->buffer.workspace, ".js") || endsWith(mm->buffer.workspace, ".go") || endsWith(mm->buffer.workspace, ".pp") || endsWith(mm->buffer.workspace, ".pss") || endsWith(mm->buffer.workspace, ".cpp") || endsWith(mm->buffer.workspace, ".pl") || endsWith(mm->buffer.workspace, ".html") || endsWith(mm->buffer.workspace, ".pdf") || endsWith(mm->buffer.workspace, ".tex") || endsWith(mm->buffer.workspace, ".sh") || endsWith(mm->buffer.workspace, ".css") || endsWith(mm->buffer.workspace, ".out") || endsWith(mm->buffer.workspace, ".log") || endsWith(mm->buffer.workspace, ".png") || endsWith(mm->buffer.workspace, ".jpg") || endsWith(mm->buffer.workspace, ".jpeg") || endsWith(mm->buffer.workspace, ".bmp") || endsWith(mm->buffer.workspace, ".mp3") || endsWith(mm->buffer.workspace, ".wav") || endsWith(mm->buffer.workspace, "aux") || endsWith(mm->buffer.workspace, ".tar") || endsWith(mm->buffer.workspace, ".gz") || endsWith(mm->buffer.workspace, "/")) { mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "\\texttt{"); get(mm); add(mm, "}"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ } // mark up language names if (0 == strcmp(mm->buffer.workspace, "python") || 0 == strcmp(mm->buffer.workspace, "java") || 0 == strcmp(mm->buffer.workspace, "ruby") || 0 == strcmp(mm->buffer.workspace, "perl") || 0 == strcmp(mm->buffer.workspace, "tcl") || 0 == strcmp(mm->buffer.workspace, "rust") || 0 == strcmp(mm->buffer.workspace, "swift") || 0 == strcmp(mm->buffer.workspace, "markdown") || 0 == strcmp(mm->buffer.workspace, "c") || 0 == strcmp(mm->buffer.workspace, "c++")) { mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "\\textit{\\texttt{"); get(mm); add(mm, "}}"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ } // paths and directories ? if (strncmp(mm->buffer.workspace, "../", strlen("../")) == 0 && 0 != strcmp(mm->buffer.workspace, "../")) { mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "\\texttt{"); get(mm); add(mm, "}"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ } if (strncmp(mm->buffer.workspace, "\"", strlen("\"")) == 0 && endsWith(mm->buffer.workspace, "\"") && 0 != strcmp(mm->buffer.workspace, "\"\"") && 0 != strcmp(mm->buffer.workspace, "\"")) { // filenames in quotes /* clip */ if (*mm->buffer.workspace != 0) { mm->buffer.workspace[strlen(mm->buffer.workspace)-1] = '\0'; } clop(mm); put(mm); // quoted uppercase words in headings if (workspaceInClassType(mm, "[A-Z]")) { // add LaTeX curly quotes to the heading word mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "``"); get(mm); add(mm, "''"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "uuword*"); push(mm); goto parse; } // markup language names if (0 == strcmp(mm->buffer.workspace, "python") || 0 == strcmp(mm->buffer.workspace, "java") || 0 == strcmp(mm->buffer.workspace, "ruby") || 0 == strcmp(mm->buffer.workspace, "perl") || 0 == strcmp(mm->buffer.workspace, "tcl") || 0 == strcmp(mm->buffer.workspace, "rust") || 0 == strcmp(mm->buffer.workspace, "swift") || 0 == strcmp(mm->buffer.workspace, "markdown") || 0 == strcmp(mm->buffer.workspace, "c") || 0 == strcmp(mm->buffer.workspace, "c++") || 0 == strcmp(mm->buffer.workspace, "forth")) { mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "``\\textit{\\texttt{"); get(mm); add(mm, "}}''"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ } // markup filenames and some unix and pep/nom names as fixed-pitch // font. if (0 == strcmp(mm->buffer.workspace, "pep") || 0 == strcmp(mm->buffer.workspace, "parse>") || 0 == strcmp(mm->buffer.workspace, "print") || 0 == strcmp(mm->buffer.workspace, "pop") || 0 == strcmp(mm->buffer.workspace, "push") || 0 == strcmp(mm->buffer.workspace, "get") || 0 == strcmp(mm->buffer.workspace, "put") || 0 == strcmp(mm->buffer.workspace, ".reparse") || 0 == strcmp(mm->buffer.workspace, ".restart") || 0 == strcmp(mm->buffer.workspace, "add") || 0 == strcmp(mm->buffer.workspace, "sed") || 0 == strcmp(mm->buffer.workspace, "awk") || 0 == strcmp(mm->buffer.workspace, "grep") || 0 == strcmp(mm->buffer.workspace, "pep") || 0 == strcmp(mm->buffer.workspace, "nom") || 0 == strcmp(mm->buffer.workspace, "less") || 0 == strcmp(mm->buffer.workspace, "stdin") || 0 == strcmp(mm->buffer.workspace, "stdout") || 0 == strcmp(mm->buffer.workspace, "bash") || endsWith(mm->buffer.workspace, ".h") || endsWith(mm->buffer.workspace, ".c") || endsWith(mm->buffer.workspace, ".a") || endsWith(mm->buffer.workspace, ".txt") || endsWith(mm->buffer.workspace, ".doc") || endsWith(mm->buffer.workspace, ".py") || endsWith(mm->buffer.workspace, ".rb") || endsWith(mm->buffer.workspace, ".rs") || endsWith(mm->buffer.workspace, ".java") || endsWith(mm->buffer.workspace, ".class") || endsWith(mm->buffer.workspace, ".tcl") || endsWith(mm->buffer.workspace, ".tk") || endsWith(mm->buffer.workspace, ".sw") || endsWith(mm->buffer.workspace, ".js") || endsWith(mm->buffer.workspace, ".go") || endsWith(mm->buffer.workspace, ".pp") || endsWith(mm->buffer.workspace, ".pss") || endsWith(mm->buffer.workspace, ".cpp") || endsWith(mm->buffer.workspace, ".pl") || endsWith(mm->buffer.workspace, ".html") || endsWith(mm->buffer.workspace, ".pdf") || endsWith(mm->buffer.workspace, ".tex") || endsWith(mm->buffer.workspace, ".sh") || endsWith(mm->buffer.workspace, ".css") || endsWith(mm->buffer.workspace, ".out") || endsWith(mm->buffer.workspace, ".log") || endsWith(mm->buffer.workspace, ".png") || endsWith(mm->buffer.workspace, ".jpg") || endsWith(mm->buffer.workspace, ".jpeg") || endsWith(mm->buffer.workspace, ".bmp") || endsWith(mm->buffer.workspace, ".mp3") || endsWith(mm->buffer.workspace, ".wav") || endsWith(mm->buffer.workspace, "aux") || endsWith(mm->buffer.workspace, ".tar") || endsWith(mm->buffer.workspace, ".gz") || endsWith(mm->buffer.workspace, ";")) { mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "``\\texttt{"); get(mm); add(mm, "}''"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ } // everything else in quotes (but only words without spaces!) if (0 != strcmp(mm->buffer.workspace, "")) { mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "``\\textit{"); get(mm); add(mm, "}''"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ } } // filenames // crude pattern checking. if (strncmp(mm->buffer.workspace, "/", strlen("/")) == 0 && 0 != strcmp(mm->buffer.workspace, "/")) { /* clip */ if (*mm->buffer.workspace != 0) { mm->buffer.workspace[strlen(mm->buffer.workspace)-1] = '\0'; } if (endsWith(mm->buffer.workspace, ".")) { mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "\\texttt{"); get(mm); add(mm, "}"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ } /* clip */ if (*mm->buffer.workspace != 0) { mm->buffer.workspace[strlen(mm->buffer.workspace)-1] = '\0'; } if (endsWith(mm->buffer.workspace, ".")) { mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "\\texttt{"); get(mm); add(mm, "}"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ } /* clip */ if (*mm->buffer.workspace != 0) { mm->buffer.workspace[strlen(mm->buffer.workspace)-1] = '\0'; } if (endsWith(mm->buffer.workspace, ".")) { mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "\\texttt{"); get(mm); add(mm, "}"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ } } // emphasis is *likethis* (only words, not phrases) if (strncmp(mm->buffer.workspace, "*", strlen("*")) == 0 && endsWith(mm->buffer.workspace, "*") && 0 != strcmp(mm->buffer.workspace, "**")) { /* clip */ if (*mm->buffer.workspace != 0) { mm->buffer.workspace[strlen(mm->buffer.workspace)-1] = '\0'; } clop(mm); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "\\textbf{\\emph{"); get(mm); add(mm, "}}"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ } // && starting a line marks the document title // the document 'title' after && or first heading, & has already // been escaped if (0 == strcmp(mm->buffer.workspace, "\\&\\&")) { mm->buffer.workspace[0] = '\0'; /* clear */ count(mm); if (0 == strcmp(mm->buffer.workspace, "1")) { mm->buffer.workspace[0] = '\0'; /* clear */ while ((strchr(" \t\f", mm->peep) != NULL) && readc(mm)) {} /* while */ mm->buffer.workspace[0] = '\0'; /* clear */ while (!(strchr("\n", mm->peep) != NULL) && readc(mm)) {} /* while */ put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "\\centerline{\\Large \\bf "); get(mm); add(mm, "} \\medskip \n"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ } } // A quote, starting the line if (0 == strcmp(mm->buffer.workspace, "quote:")) { mm->buffer.workspace[0] = '\0'; /* clear */ count(mm); if (0 == strcmp(mm->buffer.workspace, "1")) { // \begin{center} // {\huge \`\`}\textit{$quote}{\huge ''} // \textsc{$quoteauthor} // \end{center} mm->buffer.workspace[0] = '\0'; /* clear */ while ((strchr(" \t\f", mm->peep) != NULL) && readc(mm)) {} /* while */ mm->buffer.workspace[0] = '\0'; /* clear */ while (!(strchr("\n", mm->peep) != NULL) && readc(mm)) {} /* while */ put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "\\begin{center}{\\huge ``}\\textit{"); get(mm); add(mm, "}{\\huge ''}\\end{center} \n"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ } } mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "word*"); } pop(mm); // ------------- // 2 tokens // ellide text if (0 == strcmp(mm->buffer.workspace, "text*text*") || 0 == strcmp(mm->buffer.workspace, "word*text*") || 0 == strcmp(mm->buffer.workspace, "word*word*") || 0 == strcmp(mm->buffer.workspace, "text*word*") || 0 == strcmp(mm->buffer.workspace, "word*uuword*") || 0 == strcmp(mm->buffer.workspace, "text*uuword*") || 0 == strcmp(mm->buffer.workspace, "uutext*word*") || 0 == strcmp(mm->buffer.workspace, "uuword*word*")) { mm->buffer.workspace[0] = '\0'; /* clear */ get(mm); add(mm, " "); increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "text*"); push(mm); goto parse; } // tokenlist: // --- >> 4dots codeblock codeline emline nl text uutext uuword word // codeblock, // remove pesky newline tokens, 4dots handled elsewhere // not really working if (0 == strcmp(mm->buffer.workspace, "nl*text*") || 0 == strcmp(mm->buffer.workspace, "nl*word*") || 0 == strcmp(mm->buffer.workspace, "bl*text*") || 0 == strcmp(mm->buffer.workspace, "bl*word*")) { mm->buffer.workspace[0] = '\0'; /* clear */ get(mm); increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "text*"); push(mm); goto parse; } if (0 == strcmp(mm->buffer.workspace, "nl*dash*")) { mm->buffer.workspace[0] = '\0'; /* clear */ get(mm); increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "dash*"); push(mm); goto parse; } if (0 == strcmp(mm->buffer.workspace, "nl*emline*") || 0 == strcmp(mm->buffer.workspace, "bl*emline*")) { mm->buffer.workspace[0] = '\0'; /* clear */ increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "emline*"); push(mm); goto parse; } // We are using a dummy nl* token at the start of the doc, so the // codeblock* codeline* etc tokens are not able to be the first token // of the document. So we can remove the !"codeblock*". clause. // multiline codeblocks with no caption if (endsWith(mm->buffer.workspace, "codeblock*") && strncmp(mm->buffer.workspace, "emline*", strlen("emline*")) != 0) { mm->buffer.workspace[0] = '\0'; /* clear */ get(mm); add(mm, "\n\n \\begin{tabular}{l}\n "); increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ add(mm, " \\end{tabular} \n"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "text*"); push(mm); goto parse; } // single line code with no caption if (endsWith(mm->buffer.workspace, "codeline*") && strncmp(mm->buffer.workspace, "emline*", strlen("emline*")) != 0) { mm->buffer.workspace[0] = '\0'; /* clear */ get(mm); add(mm, "\n\n \\begin{tabular}{l}\n "); increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ add(mm, " \\end{tabular} \n"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "text*"); push(mm); goto parse; } // eliminate emline* tokens (not followed by codeblock/line) // the logic is slightly different because emline* is significant before // other tokens, not after. // also, consider emline*text*nl* if (strncmp(mm->buffer.workspace, "emline*", strlen("emline*")) == 0 && !endsWith(mm->buffer.workspace, "nl*") && !endsWith(mm->buffer.workspace, "codeline*") && !endsWith(mm->buffer.workspace, "codeblock*")) { replace(mm, "emline*", "text*"); /* replace */ push(mm); push(mm); // make emline display on its own line, even when not // followed by codeline/codeblock. LaTeX will treat a blank line // as a paragraph break, but \newline or \\ could be used. if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ add(mm, "\n\n"); get(mm); add(mm, "\n\n"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ goto parse; } // remove insignificant 4dots* tokens, // 4 dots (....) marks a subheading and always comes at the end of // all capitals line. Just replacing the 4dots token with a text // token is safer and more logical. if (endsWith(mm->buffer.workspace, "4dots*") && strncmp(mm->buffer.workspace, "uutext*", strlen("uutext*")) != 0 && strncmp(mm->buffer.workspace, "uuword*", strlen("uuword*")) != 0) { replace(mm, "4dots*", "text*"); /* replace */ push(mm); push(mm); goto parse; } // remove insignificant ---* tokens if (endsWith(mm->buffer.workspace, "---*") && strncmp(mm->buffer.workspace, "nl*", strlen("nl*")) != 0 && strncmp(mm->buffer.workspace, "bl*", strlen("bl*")) != 0) { mm->buffer.workspace[0] = '\0'; /* clear */ get(mm); add(mm, " "); increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "text*"); push(mm); goto parse; } // remove insignificant >>* tokens // lets assume that codelines cant start a document? Or lets // generate a dummy nl* token at the start of the document to // make parsing easier. // !">>*".E">>*".!B"nl*" { if (endsWith(mm->buffer.workspace, ">>*") && strncmp(mm->buffer.workspace, "nl*", strlen("nl*")) != 0 && strncmp(mm->buffer.workspace, "bl*", strlen("bl*")) != 0) { mm->buffer.workspace[0] = '\0'; /* clear */ get(mm); add(mm, " "); increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "text*"); push(mm); goto parse; } // ellide upper case text if (0 == strcmp(mm->buffer.workspace, "uuword*uuword*") || 0 == strcmp(mm->buffer.workspace, "uutext*uuword*")) { mm->buffer.workspace[0] = '\0'; /* clear */ get(mm); add(mm, " "); increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "uutext*"); push(mm); goto parse; } // a blank line token for terminating lists etc // bl/bl should not happen really if (0 == strcmp(mm->buffer.workspace, "nl*nl*") || 0 == strcmp(mm->buffer.workspace, "bl*nl*") || 0 == strcmp(mm->buffer.workspace, "bl*bl*")) { mm->buffer.workspace[0] = '\0'; /* clear */ get(mm); increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "bl*"); push(mm); goto parse; } // ellide multiple newlines //"nl*nl*" { // clear; get; ++; get; --; put; clear; // add "nl*"; push; .reparse //} // code line (starts with >>) if (0 == strcmp(mm->buffer.workspace, "bl*>>*") || 0 == strcmp(mm->buffer.workspace, "nl*>>*")) { // ignore leading space. mm->buffer.workspace[0] = '\0'; /* clear */ while ((strchr(" \t\f", mm->peep) != NULL) && readc(mm)) {} /* while */ mm->buffer.workspace[0] = '\0'; /* clear */ // escape | so it doesnt terminate the verb environment. // but how to do it? or use lstlisting while (!(strchr("\n", mm->peep) != NULL) && readc(mm)) {} /* while */ put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, " \\verb| "); get(mm); add(mm, " |\n"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "codeline*"); push(mm); goto parse; } // code block marker if (0 == strcmp(mm->buffer.workspace, "bl*---*") || 0 == strcmp(mm->buffer.workspace, "nl*---*")) { mm->buffer.workspace[0] = '\0'; /* clear */ until(mm, ",,,"); /* clip */ if (*mm->buffer.workspace != 0) { mm->buffer.workspace[strlen(mm->buffer.workspace)-1] = '\0'; } /* clip */ if (*mm->buffer.workspace != 0) { mm->buffer.workspace[strlen(mm->buffer.workspace)-1] = '\0'; } /* clip */ if (*mm->buffer.workspace != 0) { mm->buffer.workspace[strlen(mm->buffer.workspace)-1] = '\0'; } // remove excessive indentation. replace(mm, "\n ", "\n"); /* replace */ put(mm); while ((strchr(",", mm->peep) != NULL) && readc(mm)) {} /* while */ mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "\n \\begin{lstlisting}[breaklines]"); get(mm); add(mm, "\n \\end{lstlisting} \n"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "codeblock*"); push(mm); goto parse; } // a code block with its preceding description if (0 == strcmp(mm->buffer.workspace, "emline*codeblock*")) { mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "\n\n \\begin{tabular}{l}\n "); get(mm); add(mm, " \\\\ "); increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ add(mm, " \\end{tabular} \n"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "text*"); push(mm); goto parse; } // a code line with its preceding description // add some tabular LaTeX markup here. if (0 == strcmp(mm->buffer.workspace, "emline*codeline*")) { mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "\n\n \\begin{tabular}{l}\n "); get(mm); add(mm, " \\\\ \n"); increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ add(mm, " \\end{tabular} \n"); //add " \\end{figure}"; put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "text*"); push(mm); goto parse; } // probably indicates an empty - at the end of a list // add a dummy text token if (0 == strcmp(mm->buffer.workspace, "olist*bl*") || 0 == strcmp(mm->buffer.workspace, "ulist*bl*") || 0 == strcmp(mm->buffer.workspace, "dlist*bl*")) { push(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "empty"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "\n\n"); increment(mm); /* ++ */ put(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "text*bl*"); push(mm); push(mm); goto parse; } // or use this to terminate the list, and so allow nested lists if (0 == strcmp(mm->buffer.workspace, "olist*dash*") || 0 == strcmp(mm->buffer.workspace, "ulist*dash*") || 0 == strcmp(mm->buffer.workspace, "dlist*dash*")) { push(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "empty"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "text*dash*"); push(mm); push(mm); goto parse; } pop(mm); // ------------- // 3 tokens if (0 == strcmp(mm->buffer.workspace, "olist*word*dash*") || 0 == strcmp(mm->buffer.workspace, "ulist*word*dash*") || 0 == strcmp(mm->buffer.workspace, "dlist*word*dash*") || 0 == strcmp(mm->buffer.workspace, "olist*word*bl*") || 0 == strcmp(mm->buffer.workspace, "ulist*word*bl*") || 0 == strcmp(mm->buffer.workspace, "dlist*word*bl*")) { replace(mm, "word*", "text*"); /* replace */ // or dont reparse // push; push; push; .reparse } // eliminate dashes that are not part of a list // eg: ulist*dash* olist*text*dash* dlist*word*dash* // the logic is tricky, how do we know there are really 3 tokens // here, and not 2. This is the problem with negative tests. // doesnt matter because not altering attributes here. if (endsWith(mm->buffer.workspace, "dash*")) { if (strncmp(mm->buffer.workspace, "ulist*text*", strlen("ulist*text*")) != 0 && strncmp(mm->buffer.workspace, "olist*text*", strlen("olist*text*")) != 0 && strncmp(mm->buffer.workspace, "dlist*text*", strlen("dlist*text*")) != 0) { replace(mm, "dash*", "text*"); /* replace */ push(mm); push(mm); push(mm); goto parse; } } if (0 == strcmp(mm->buffer.workspace, "olist*text*dash*")) { mm->buffer.workspace[0] = '\0'; /* clear */ get(mm); add(mm, "\n \\item "); increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "olist*"); push(mm); goto parse; } // could be ellided, but for readability, no if (0 == strcmp(mm->buffer.workspace, "ulist*text*dash*")) { mm->buffer.workspace[0] = '\0'; /* clear */ get(mm); add(mm, "\n \\item "); increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "ulist*"); push(mm); goto parse; } // if (0 == strcmp(mm->buffer.workspace, "dlist*text*dash*")) { mm->buffer.workspace[0] = '\0'; /* clear */ // already have \item start get(mm); add(mm, " "); increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ // also, put a \verbatim in [] because text is not escaped?? add(mm, "\n \\item["); while (!(strchr("\n:", mm->peep) != NULL) && readc(mm)) {} /* while */ add(mm, "] "); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "dlist*"); push(mm); goto parse; } // finish off the ordered list, also could finish it off with // ulist*dash* ?? if (0 == strcmp(mm->buffer.workspace, "olist*text*bl*")) { mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "\n \\begin{enumerate}\n"); get(mm); add(mm, "\n \\item "); increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ add(mm, "\n \\end{enumerate}\n\n"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ // insert the blankline attribute add(mm, "\n\n"); increment(mm); /* ++ */ put(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "text*bl*"); push(mm); push(mm); goto parse; } // finish off the unordered list if (0 == strcmp(mm->buffer.workspace, "ulist*text*bl*")) { mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "\n \\begin{itemize}\n"); get(mm); add(mm, "\n \\item "); increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ add(mm, "\n \\end{itemize}\n\n"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ // insert the blankline attribute add(mm, "\n\n"); increment(mm); /* ++ */ put(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "text*bl*"); push(mm); push(mm); goto parse; } // finish off the description list if (0 == strcmp(mm->buffer.workspace, "dlist*text*bl*")) { // or check here if it is D/- or d/- for nextline style // or use \hfill \\ on each item which also works mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "\n \\begin{description}[style=nextline]\n"); get(mm); add(mm, "\n "); increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ add(mm, "\n \\end{description}\n\n"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ // insert the blankline attribute add(mm, "\n\n"); increment(mm); /* ++ */ put(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "text*bl*"); push(mm); push(mm); goto parse; } // top level headings, all upper case on the line in the source document. // dont need a "heading" token because we dont parse the document as a // heirarchy, we just render things as we find them in the stream. if (0 == strcmp(mm->buffer.workspace, "nl*uutext*nl*") || 0 == strcmp(mm->buffer.workspace, "nl*uuword*nl*") || 0 == strcmp(mm->buffer.workspace, "bl*uutext*nl*") || 0 == strcmp(mm->buffer.workspace, "bl*uuword*nl*")) { mm->buffer.workspace[0] = '\0'; /* clear */ // Check that heading is at least 4 chars increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ /* clip */ if (*mm->buffer.workspace != 0) { mm->buffer.workspace[strlen(mm->buffer.workspace)-1] = '\0'; } /* clip */ if (*mm->buffer.workspace != 0) { mm->buffer.workspace[strlen(mm->buffer.workspace)-1] = '\0'; } /* clip */ if (*mm->buffer.workspace != 0) { mm->buffer.workspace[strlen(mm->buffer.workspace)-1] = '\0'; } if (0 == strcmp(mm->buffer.workspace, "")) { add(mm, "nl*text*nl*"); push(mm); push(mm); push(mm); goto parse; } mm->buffer.workspace[0] = '\0'; /* clear */ // make headings capital case increment(mm); /* ++ */ get(mm); // capitalise even 1st word in latex curly quotes // add "<buffer.workspace, "``", strlen("``")) == 0) { clop(mm); clop(mm); } char *s = mm->buffer.workspace; /* cap */ if (*s) { *s = toupper((unsigned char) *s); s++; } while (*s) { *s = tolower((unsigned char) *s); s++; } put(mm); replace(mm, "''", ""); /* replace */ // add open curly quotes if there before. if (strcmp(mm->buffer.workspace, mm->tape.cells[mm->tape.currentCell].text) != 0) { mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "``"); get(mm); } put(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ mm->buffer.workspace[0] = '\0'; /* clear */ get(mm); // newline add(mm, "\\section{"); increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ add(mm, "}"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ // transfer nl value increment(mm); /* ++ */ increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ add(mm, "text*nl*"); push(mm); push(mm); goto parse; } // simple reductions if (0 == strcmp(mm->buffer.workspace, "nl*text*nl*") || 0 == strcmp(mm->buffer.workspace, "nl*word*nl*") || 0 == strcmp(mm->buffer.workspace, "bl*text*nl*") || 0 == strcmp(mm->buffer.workspace, "bl*word*nl*") || 0 == strcmp(mm->buffer.workspace, "text*text*nl*") || 0 == strcmp(mm->buffer.workspace, "emline*text*nl*")) { mm->buffer.workspace[0] = '\0'; /* clear */ get(mm); increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ increment(mm); /* ++ */ increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ put(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ mm->buffer.workspace[0] = '\0'; /* clear */ // transfer newline value add(mm, "text*nl*"); push(mm); push(mm); goto parse; } pop(mm); // ------------- // 4 tokens // sub headings, if (0 == strcmp(mm->buffer.workspace, "nl*uutext*4dots*nl*") || 0 == strcmp(mm->buffer.workspace, "nl*uuword*4dots*nl*") || 0 == strcmp(mm->buffer.workspace, "bl*uutext*4dots*nl*") || 0 == strcmp(mm->buffer.workspace, "bl*uuword*4dots*nl*")) { mm->buffer.workspace[0] = '\0'; /* clear */ // Check that sub heading text is at least 4 chars ? // yes but need to transfer 4dots and nl // ++; get; --; clip; clip; clip; // "" { add "nl*text*nl*"; push; push; push; .reparse } mm->buffer.workspace[0] = '\0'; /* clear */ // make subheadings capital case increment(mm); /* ++ */ get(mm); // capitalise even 1st word in latex curly quotes if (strncmp(mm->buffer.workspace, "``", strlen("``")) == 0) { clop(mm); clop(mm); } char *s = mm->buffer.workspace; /* cap */ if (*s) { *s = toupper((unsigned char) *s); s++; } while (*s) { *s = tolower((unsigned char) *s); s++; } put(mm); replace(mm, "''", ""); /* replace */ // add open curly quotes if there before. if (strcmp(mm->buffer.workspace, mm->tape.cells[mm->tape.currentCell].text) != 0) { mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "``"); get(mm); } put(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ mm->buffer.workspace[0] = '\0'; /* clear */ get(mm); // newline add(mm, "\\subsection{"); increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ add(mm, "}"); put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ // transfer nl value increment(mm); /* ++ */ increment(mm); /* ++ */ increment(mm); /* ++ */ get(mm); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ add(mm, "text*nl*"); push(mm); push(mm); goto parse; } push(mm); push(mm); push(mm); push(mm); if (mm->peep == EOF) { // or use 'unstack' but does it adjust the tape pointer? pop(mm); pop(mm); pop(mm); pop(mm); pop(mm); pop(mm); // "nl*word*","nl*text*" have already been dealt with. // we would like "permissive" parsing, because this is just // a document format, not code, so will just check for starting // text token //"text*nl*","text*bl","text*" { if (strncmp(mm->buffer.workspace, "text*", strlen("text*")) == 0 || strncmp(mm->buffer.workspace, "word*", strlen("word*")) == 0) { // show the token parse stack at the top of the document increment(mm); /* ++ */ put(mm); mm->buffer.workspace[0] = '\0'; /* clear */ add(mm, "%% Document parse-stack is: "); get(mm); add(mm, "\n"); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ mm->buffer.workspace[0] = '\0'; /* clear */ // make a valid LaTeX document add(mm, ""); add(mm, "\n %% "); add(mm, "\n %% -------------------------------------------"); add(mm, "\n %% latex generated by: mark.latex.pss "); add(mm, "\n %% from source file : "); add(mm, "\n %% on: "); add(mm, "\n %% -------------------------------------------"); add(mm, "\n"); add(mm, "\n \\documentclass[a4paper,12pt]{article}"); add(mm, "\n \\usepackage[margin=4pt,noheadfoot]{geometry}"); add(mm, "\n \\usepackage{color} %% to use colours, use 'xcolor' for more"); add(mm, "\n \\usepackage{multicol} %% for multiple columns"); add(mm, "\n \\usepackage{keystroke} %% for keyboard key images"); add(mm, "\n \\usepackage[toc]{multitoc} %% for multi column table of contents"); add(mm, "\n \\usepackage{tocloft} %% to customize the table of contents"); add(mm, "\n \\setcounter{tocdepth}{2} %% only display 2 levels in the contents"); add(mm, "\n \\setlength{\\cftbeforesecskip}{0cm} %% make the toc more compact"); add(mm, "\n \\usepackage{listings} %% for nice code listings"); add(mm, "\n \\usepackage{caption} %% "); add(mm, "\n \\lstset{"); add(mm, "\n captionpos=t,"); add(mm, "\n language=bash,"); add(mm, "\n basicstyle=\\ttfamily, %% fixed pitch font"); add(mm, "\n xleftmargin=0pt, %% margin on the left outside the frames"); add(mm, "\n framexleftmargin=0pt,"); add(mm, "\n framexrightmargin=0pt,"); add(mm, "\n framexbottommargin=5pt,"); add(mm, "\n framextopmargin=5pt,"); add(mm, "\n breaklines=true, %% break long code lines"); add(mm, "\n breakatwhitespace=false, %% break long code lines anywhere"); add(mm, "\n breakindent=10pt, %% reduce the indent from 20pt to 10"); add(mm, "\n postbreak=\\mbox{{\\color{blue}\\small$\\Rightarrow$\\space}}, %% mark with arrow"); add(mm, "\n showstringspaces=false, %% dont show spaces within strings"); add(mm, "\n framerule=2pt, %% thickness of the frames"); add(mm, "\n frame=top,frame=bottom,"); add(mm, "\n rulecolor=\\color{lightgrey}, "); add(mm, "\n % frame=l"); add(mm, "\n % define special comment delimiters '##(' and ')'"); add(mm, "\n % moredelim=[s][\\color{grey}\\itshape\\footnotesize\\ttfamily]{~(}{)},"); add(mm, "\n } %% source code settings"); add(mm, "\n \\usepackage{graphicx} %% to include images"); add(mm, "\n \\usepackage{fancybox} %% boxes with rounded corners"); add(mm, "\n \\usepackage{wrapfig} %% flow text around tables, images"); add(mm, "\n \\usepackage{tabularx} %% change width of tables"); add(mm, "\n \\usepackage[table]{xcolor} %% alternate row colour tables"); add(mm, "\n \\usepackage{booktabs} %% for heavier rules in tables"); add(mm, "\n \\usepackage[small,compact]{titlesec} %% sections more compact, less space"); add(mm, "\n \\usepackage{enumitem} %% more compact and better lists"); add(mm, "\n \\setlist{noitemsep} %% reduce list item spacing"); add(mm, "\n \\usepackage{hyperref} %% make urls into hyperlinks"); add(mm, "\n \\hypersetup{ %% add pdftex if only pdf output is required"); add(mm, "\n colorlinks=false, %% set up the colours for the hyperlinks"); add(mm, "\n linkcolor=black, %% internal document links black"); add(mm, "\n urlcolor=black, %% url links black"); add(mm, "\n frenchlinks=true,"); add(mm, "\n bookmarks=true, pdfpagemode=UseOutlines}"); add(mm, "\n"); add(mm, "\n \\geometry{ left=1.0in,right=1.0in,top=1.0in,bottom=1.0in }"); add(mm, "\n %% define some colours to use"); add(mm, "\n \\definecolor{lightgrey}{gray}{0.70}"); add(mm, "\n \\definecolor{grey}{gray}{0.30}"); add(mm, "\n"); add(mm, "\n %% titlesec: create framed section headings"); add(mm, "\n %% \\titleformat{\\section}[frame]{\\normalfont}"); add(mm, "\n %% {\\filleft \\footnotesize \\enspace Section \\thesection\\enspace\\enspace}"); add(mm, "\n %% {3pt} {\\bfseries\\itshape\\filright}"); add(mm, "\n"); add(mm, "\n \\title{The Pep/nom parsing language and machine}"); add(mm, "\n \\author{m.j.bishop}"); add(mm, "\n \\date{\\today}"); add(mm, "\n \\setlength{\\parindent}{0pt}"); add(mm, "\n %% \\setlength{\\parskip}{1ex}"); add(mm, "\n"); add(mm, "\n %% label lists with stars"); add(mm, "\n \\renewcommand{\\labelitemi}{$\\star$}"); add(mm, "\n"); add(mm, "\n \\parindent=0pt"); add(mm, "\n \\parskip=6pt"); add(mm, "\n \\begin{document}"); add(mm, "\n"); add(mm, "\n "); get(mm); add(mm, "\n\\end{document} \n"); add(mm, "\n\n %% Document parsed as text*!\n"); // show parse-stack at end of doc as well increment(mm); /* ++ */ add(mm, " %% Document parse-stack is: "); get(mm); add(mm, "\n"); if (mm->tape.currentCell > 0) mm->tape.currentCell--; /* -- */ printf("%s", mm->buffer.workspace); /* print */ exit(0); } while (push(mm)) {} /* stack */ add(mm, "Document parsed unusually!\n"); add(mm, "Stack at line "); lines(mm); add(mm, " char "); chars(mm); add(mm, ": "); printf("%s", mm->buffer.workspace); /* print */ mm->buffer.workspace[0] = '\0'; /* clear */ while (pop(mm)) {} /* unstack */ printf("%s", mm->buffer.workspace); /* print */ while (push(mm)) {} /* stack */ add(mm, "\n"); printf("%s", mm->buffer.workspace); /* print */ mm->buffer.workspace[0] = '\0'; /* clear */ exit(0); } } }