8 stable releases

1.1.5 Dec 21, 2020
1.1.4 Dec 20, 2020
1.0.1 Nov 26, 2020

#1630 in Parser implementations

46 downloads per month

LGPL-3.0-or-later

370KB
743 lines

PseudoTex

PseudoTex is a compiler that translates pseudocode into its LaTex representation

In university I had to do a few reports in LaTex that had pseudocode. Translating the simple pseudocode to the LaTex commands was a huge struggle so I decided to make this tool that translates a simple pseudocode language into the LaTex equivalent commands. I hope it makes your life easier 😁.

The pseudocode that PseudoTex follows is somewhat formalized in this paper by João Leitão (check caveats).

Installing

For now there are two ways of installing PseudoTex, either by using cargo or by downloading the latest binary release.

Using cargo

λ ~/ $ cargo install pseudotex

Using latest release

Go to the repository Releases page and download the binary (Linux or macOS).

Running

λ ~/ $ pseudotex --help
PseudoTex 1.0
Bruno Anjos <bruno.vale.anjos@gmail.com>
pseudocode transpiler to latex representation

USAGE:
    pseudotex [OPTIONS]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -i, --input <input>      file name to read content from
    -o, --output <output>    file name to write content to

Caveats

Semi Colons

One main difference from the language described in the paper, is that every statement has to be followed by a semi colon. I believe this can be changed in the future, but since this made the parser easier to build i decided to take this approach.

TODO

  • Add more symbols
  • Add tests
  • Add test automation per commit
  • Add subscript

Contributing

If you'd like to contribute, please fork the repository and use a feature branch. Pull requests are warmly welcome.

Project dependencies:

Example

Here is a small example (check example_protocol.pseudo)

state:
    parents // these are parents ;
    services;
    myId;
    fallback;

upon init do:
    fallback = getFallback();
    myId = randomString();

upon event Receive(QUALITY_NOT_ASSURED, service, location) do:
    newChild = getNodeClosestTo(location);
    trigger Send(DEPLOY_SERVICE, newChild, service, myself);
    call addChild(service, newChild);

upon event Receive(DEPLOY_SERVICE, service, sender) do:
    if service !in services:
        services = services unite {service};
    end
    call updateParent(service, sender);

procedure updateParent(service, parent):
    if service.Parent == parent:
        return;
    end
    parents = parents unite {parent};
    service.parent = parent;
    foreach child in service.children:
        trigger Send(GRANDPARENT, child, service, parent, myself);
    end

upon event Receive(GRANDPARENT, service, grandparent, sender) do:
    service.grandparent = grandparent;

procedure updateChildren(service):
    orderedChild = order(service.children);
    foreach child in service.children:
        trigger Send(SIBLINGS, child, service, orderedChild);
    end

procedure addChild(service, child):
    if child !in children:
        children = children unite {child};
    end

    if child !in service.children:
        service.children = service.children unite {child};
        servicesByChild[child] = servicesByChild[child] unite {service};
        call updateChildren(service);
    end

This pseudocode generates the following LaTeX:

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[ruled,vlined,linesnumbered]{algorithm2e}
\usepackage{amssymb}
\begin{document}
{{\DontPrintSemicolon
\SetAlgoNoLine
\LinesNumberedHidden
\SetFuncSty{textbf}
\begin{algorithm}[ht]
\BlankLine
\BlankLine
\BlankLine

\SetKwFunction{FunctionID}{State}
\SetKwProg{Fn}{}{:}{}
\Fn{\FunctionID}{
parents
// these are parents
\;services
\;myId
\;fallback
}

\;\SetKwFunction{FunctionID}{Init}
\SetKwProg{Fn}{Upon }{ do:}{}
\Fn{\FunctionID}{
fallback $\longleftarrow$ \FuncSty{getFallback(}\ArgSty{}\FuncSty{)}
\;myId $\longleftarrow$ \FuncSty{randomString(}\ArgSty{}\FuncSty{)}
}

\;\SetKwFunction{FunctionID}{Receive}
\SetKwProg{Fn}{Upon event }{ do:}{}
\Fn{\FunctionID{QUALITY\_NOT\_ASSURED, service, location}}{
newChild $\longleftarrow$ \FuncSty{getNodeClosestTo(}\ArgSty{location}\FuncSty{)}
\;\FuncSty{Trigger} \FuncSty{Send(}\ArgSty{DEPLOY\_SERVICE, newChild, service, myself}\FuncSty{)}
\;\FuncSty{Call addChild(}\ArgSty{service, newChild}\FuncSty{)}
}

\;\SetKwFunction{FunctionID}{Receive}
\SetKwProg{Fn}{Upon event }{ do:}{}
\Fn{\FunctionID{DEPLOY\_SERVICE, service, sender}}{
\If{service $\notin$ services}{services $\longleftarrow$ services $\cup$ \{service\}}
\;\FuncSty{Call updateParent(}\ArgSty{service, sender}\FuncSty{)}
}

\;\SetKwFunction{FunctionID}{updateParent}
\SetKwProg{Fn}{Procedure }{:}{}
\Fn{\FunctionID{service, parent}}{
\If{service.Parent == parent}{return}
\;parents $\longleftarrow$ parents $\cup$ \{parent\}
\;service.parent $\longleftarrow$ parent
\;\ForEach{child $\in$ service.children}{\FuncSty{Trigger} \FuncSty{Send(}\ArgSty{GRANDPARENT, child, service, parent, myself}\FuncSty{)}}
}

\;\SetKwFunction{FunctionID}{Receive}
\SetKwProg{Fn}{Upon event }{ do:}{}
\Fn{\FunctionID{GRANDPARENT, service, grandparent, sender}}{
service.grandparent $\longleftarrow$ grandparent
}

\;\SetKwFunction{FunctionID}{updateChildren}
\SetKwProg{Fn}{Procedure }{:}{}
\Fn{\FunctionID{service}}{
orderedChild $\longleftarrow$ \FuncSty{order(}\ArgSty{service.children}\FuncSty{)}
\;\ForEach{child $\in$ service.children}{\FuncSty{Trigger} \FuncSty{Send(}\ArgSty{SIBLINGS, child, service, orderedChild}\FuncSty{)}}
}

\;\SetKwFunction{FunctionID}{addChild}
\SetKwProg{Fn}{Procedure }{:}{}
\Fn{\FunctionID{service, child}}{
\If{child $\notin$ children}{children $\longleftarrow$ children $\cup$ \{child\}}
\;\If{child $\notin$ service.children}{service.children $\longleftarrow$ service.children $\cup$ \{child\}
\;servicesByChild[child] $\longleftarrow$ servicesByChild[child] $\cup$ \{service\}
\;\FuncSty{Call updateChildren(}\ArgSty{service}\FuncSty{)}}
}

\BlankLine
\BlankLine
\BlankLine
\end{algorithm}
\end{document}

Which ultimately generates the following pdf:

Licensing

The code in this project is licensed under GPL-3.0.

Dependencies

~3.5–5.5MB
~101K SLoC