1 Dednat6: an extensible (semi-)preprocessor for LuaL A T EX that understands Eduardo Ochs - UFF TUG 2018 - Rio de Janeiro, 20-22 jul 2018 http://angg.twu.net/dednat6.html diagrams in ASCII art
2 Prehistory: dednat.icn a 2D ascii art version of each diagram in comments for each diagram was so opaque that I had to keep so that I wouldn’t get lost... and it had lots of tree diagrams like these: My master’s thesis was partly about Natural Deduction, [ x ] 1 [ a ] 1 f a → b f ( x ) g b b → c g ( f ( x )) c λx.g ( f ( x )) 1 a → c 1 I used proof.sty to typeset them, but the code
3 Prehistory: dednat.icn (2) \mathstrut g } } } \mathstrut f } & \mathstrut [x]^1 & \infer[{}]{ \mathstrut f(x) }{ \infer[{}]{ \mathstrut g(f(x)) }{ %: %: ----------1 %: g(f(x)) %: -------- %: f(x) g %: -------- %: [x]^1 f ...like this: $$ [ x ] 1 f f ( x ) g %: λ x.g(f(x)) g ( f ( x )) $$\infer[{1}]{ \mathstrut λ x.g(f(x)) }{ λx.g ( f ( x )) 1
4 Prehistory: dednat.icn (3) \mathstrut g } } } \mathstrut f } & \mathstrut [x]^1 & \infer[{}]{ \mathstrut f(x) }{ \infer[{}]{ \mathstrut g(f(x)) }{ \defded{foo}{ � %: ^foo %: %: ----------1 %: g(f(x)) %: -------- %: f(x) g %: -------- %: [x]^1 f dednat.icn would only look for trees in ‘ %: ’-lines, I made the syntax of the 2D ascii art trees more rigid ...then I realized that I could automate the boring part. and would put the ‘ \defded ’s in another fjle... and wrote a parser (in Icon!) that understood it. A tree with a name tag like ^foo below it would become a \defded{foo}{...} — \infer[{1}]{ \mathstrut λ x.g(f(x)) }{ %: λ x.g(f(x))
5 %: ----------1 Running ‘ dednat.icn myfile.tex ’ would generate � $$\ded{foo}$$ % %: ^foo Prehistory: dednat.icn (4) %: %: g(f(x)) %: -------- %: f(x) g %: -------- %: [x]^1 f % \input myfile.auto.dnt So that I could have this, in myfile.tex : the fjle myfile.auto.dnt . [ x ] 1 f f ( x ) g g ( f ( x )) %: λ x.g(f(x)) λx.g ( f ( x )) 1
6 Prehistory: dednat4.lua dednat.icn understood one kind of “head”: ‘ %: ’-lines would be scanned for trees. dednat4.lua understood three kinds of heads: ‘ %: ’-lines would be scanned for trees, ‘ %L ’-lines contained Lua code, ‘ %D ’-lines contained diagrams in a Forth-based language. New heads could be added dynamically. (Actually I also had a head to defjne abbreviations like ‘ -> ’ → ‘ \to ’)
7 $$\diag{BCCL-std}$$ � � � ✤ � � % � %D enddiagram %D )) %D b0 relplace 20 7 \pbsymbol{7} %D b2 b3 -> .plabel= a f %D b1 b3 -> .plabel= r z %D b0 b2 -> .plabel= l z' � ✤ %D )) � � � � � � ✤ � � � ✤ � � � Dednat4.lua’s language for diagrams � %D b0 b1 -> .plabel= b f' � %D B1 B3 midpoint B5 B7 midpoint dharrownodes nil 20 nil <-| %D B0 B2 midpoint B4 B6 midpoint dharrownodes nil 20 nil |-> %D 2D 100 B0 <====================== B1 %D 2D \\ | \\| %D 2D -\\ -\\ %D 2D | \\ | \\ %D 2D v \\ v \\ %D 2D +20 B2 <\\> B2' ============== B3 \\ %D 2D /\ \/ /\ \/ %D 2Dx 100 +45 +55 +45 %D 2D +10 b0 |---------------------> b1 %D 2D +15 \\ B4 \\ B5 %D 2D \\ - \\ - %D 2D %D 2D +20 B6 <===================== B7 %D 2D \\v \v %D 2D +35 b2 |--------------------> b3 %D 2D |-> |-> %D B6 B7 <-| B5 B7 -> .plabel= r \id that afgect parsing — that eat the next word or all %D B2 B6 <-| B3 B7 <-| %D B0 B4 |-> B1 B5 |-> %D (( %D B0 B2' midpoint B1 B3 midpoint harrownodes nil 20 nil <-| Based on Forth: stack-based, and we can defjne words %D B0 B1 <-| B0 B2 -> B0 B2' -> B1 B3 -> B2 B2' <-> B2' B3 <-| the rest of the line. Some words parse a 2D grid with coordinates for nodes; other words join nodes with arrows. %D diagram BCCL-std %D B0 .tex= f^{\prime*}P B1 .tex= P Generates code for diagxy.tex (a front-end for xypic ). f ′∗ P f ′∗ P f ′∗ P f ′∗ P P P P ◗ ❋ ❋ ✝ ◗ ✝ ❋ ❋ ◗ ❋ ❋ ◗ ◗ ❋ ❋ ◗ ❋ ❋ ◗ ◗ ❋ ❋ ❋ ❋ ❋ � f ′∗ z ∗ Σ z P ❋ z ′∗ f ∗ Σ z P z ′∗ f ∗ Σ z P z ′∗ f ∗ Σ z P ❋ f ′∗ z ∗ Σ z P f ′∗ z ∗ Σ z P z ∗ Σ z P z ∗ Σ z P z ∗ Σ z P ❋ ❋ ❋ ✝ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ✝ Σ z ′ f ′∗ P Σ z ′ f ′∗ P Σ z ′ f ′∗ P ❋ Σ z P Σ z P ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ %D B2 .tex= z^{\prime*}f^* Σ _zP B3 .tex= z^* Σ _zP ❋ ❋ ♮ � %D B4 .tex= Σ _{z'}f^{\prime*}P B5 .tex= Σ _zP ❋ BCCL ❋ id ❋ ❋ %D B6 .tex= f^* Σ _zP B7 .tex= Σ _zP ✝ %D B2' .tex= f^{\prime*}z^* Σ _zP ✝ f ∗ Σ z P f ∗ Σ z P f ∗ Σ z P f ∗ Σ z P Σ z P Σ z P Σ z P %D B4 B6 -> sl_ .plabel= l ♮ B4 B6 <- sl^ .plabel= r \BCCL X × Y Z X × Y Z Z Z ❋ ❋ f ′ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ %D (( b0 .tex= X × _{Y}Z b1 .tex= Z b2 .tex= X b3 .tex= Y ❋ ❋ ❋ z ❋ ❋ ❋ ❋ ❋ ❋ z ′ ❋ ❋ ❋ ❋ ❋ ❋ ❋ ❋ f X X Y Y
8 %D \catB \catA -> sl_ .plabel= b R � � � � ✤ � � ✤ � Dednat4.lua’s language for diagrams (2) $$\diag{adj}$$ %D %D enddiagram %D )) � %D \catB \catA <- sl^ .plabel= a L %D 2D +25 B |-> RB %D diagram adj %D 2Dx 100 +25 %D 2D 100 LA <-| A %D 2D | | %D 2D | <--> | %D LA RB harrownodes nil 20 nil <-> %D 2D v v %D (( LA A <-| %D 2D %D 2D %D B RB |-> %D LA B -> A RB -> %D 2D +15 \catB \catA LA LA A A B B RB RB L B B A A R
9 %D LA RB harrownodes nil 20 nil <-> arrow at the top of the .plabel modifjes the nodes with coordinates. as a grid, and defjne the rest of the line 2D and 2Dx eat “eat text”. $$\diag{adj}$$ %D %D enddiagram %D )) %D \catB \catA -> sl_ .plabel= b R %D \catB \catA <- sl^ .plabel= a L %D B RB |-> Dednat4.lua’s language for diagrams (3) %D 2D | <--> | (See my “Bootstrapping a Forth in 40 lines of Lua code” in the Lua Gems book... section ‘Modes”) %D diagram adj %D 2Dx 100 +25 %D 2D 100 LA <-| A %D 2D | | stack: ‘placement’ ‘label’ %D LA B -> A RB -> %D 2D v v %D 2D +25 B |-> RB %D 2D %D 2D +15 \catB \catA %D 2D %D (( LA A <-| The words in red
10 %D LA RB harrownodes nil 20 nil <-> phantom nodes for a middle harrownodes creates two topmost nodes in the stack. Arrow words connect the two nodes with coordinates. as a grid, and defjne the rest of the line 2D and 2Dx eat $$\diag{adj}$$ %D %D enddiagram %D )) %D \catB \catA -> sl_ .plabel= b R %D \catB \catA <- sl^ .plabel= a L %D B RB |-> Dednat4.lua’s language for diagrams (4) %D LA B -> A RB -> %D (( LA A <-| %D 2D %D 2D +15 \catB \catA %D 2D %D 2D +25 B |-> RB %D 2D v v %D 2D | <--> | %D 2D | | %D 2D 100 LA <-| A %D 2Dx 100 +25 %D diagram adj in the Lua Gems book... section ‘Modes”) (See my “Bootstrapping a Forth in 40 lines of Lua code” horizontal arrow.
11 Dednat4.lua’s language for diagrams (5) functions low-level shows how the print(arrows_to_TeX()) print(arrows[4]:TeX()) print(arrows[3]:TeX()) print(arrows[2]:TeX()) print(arrow_to_TeX(arrows[1])) = arrows storearrow(DxyLiteral {"literal foobar"}) storearrow(DxyPlace {nodes["a"]}) storearrow(DxyArrow {from="a", to="b", shape=".>"}) placement="a"}) slide="5pt", label="up", storearrow(DxyArrow {from="a", to="b", shape="|->", = nodes storenode {TeX="b", tag="b", x=140, y=100} storenode {TeX="a", tag="a", x=100, y=100} require "diagforth" we can put Lua code in ‘ %L ’ lines between ‘ %D ’ lines, and... stack until the depth becomes what it was at the ‘ (( ’, sl^ and sl_ slide the topmost arrow in the stack, enddiagram outputs the table arrows as diagxy code, work... For the sake of completeness... diagram resets several tables, The ‘ )) ’ in a (( . . . )) block drops all top items from the ← this Lua code
12 EX... A T current line”, and send the defs to L ‘ \pu ’ means “process all pending heads until the each diagram in a ‘ %D ’ block generates a ‘ \defdiag ’... Each tree in a ‘ %: ’ block generates a ‘ \defded ’ In fact there are synchronization points. pretends to run at the same time as T Dednat6: a semi-preprocessor lines with heads like ‘ %L ’, ‘ %: ’, ‘ %D ’, etc, In Dednat6 the Lua code that processes the EX. A T it generates a foo.auto.dnt from foo.tex , Dednat4 is a real pre-processor — EX— and it runs before L
Recommend
More recommend