IUT de Lannion Pseudocode compiler (transpiler).
Psdc is a transpiler, designed to automate the painstaking task of rewriting Pseudocode programs to other languages.
Given any Pseudocode program (valid or invalid), Psdc produces an equivalent program in the target language to the best of its ability, providing helpful diagnostics along the way.
Equivalent
here is defined as:
- Equivalence in validity: a valid Pseudocode program transpiles to a valid program in the target language. An invalid program (with compiler errors) may be invalid in the target language.
- Equivalence in behavior: a valid Pseudocode program exhibits the expected behavior in the target language. Since Pseudocode programs can't be executed, the expected behavior of a program is determined by the Standard (yet to be written).
- Equivalence in semantics: a Pseudocode program and its transpiled counterpart must be semantically equivalent. This implies:
- same identifiers (except where target language keywords are used)
- same declaration order (as possible considering the rules of the target language)
- Equivalence in representation: the generated code should be human-readable and easily modifiable, with a clear correspondence between the input pseudocode and the output code.
More information in The Zen of Pseudocode.
1. Input Pseudocode (sudoku.psc)
My pitiful program for S1.01
/*
Algorithme programme principal Sudoku
*/
programme Sudoku c'est
// Un jeu de Sudoku
constante entier N := 3;
constante entier NB_FICHIERS_GRILLES := 10;
constante entier LONGUEUR_MAX_COMMANDE := 64;
constante entier COTE_GRILLE := N * N;
type t_grilleEntier = tableau[COTE_GRILLE, COTE_GRILLE] de entier;
début
grilleJeu : t_grilleEntier;
ligneCurseur, colonneCurseur : entier;
partieAbandonnée : booléen;
commandeRéussie : booléen;
commande : chaîne(LONGUEUR_MAX_COMMANDE);
partieAbandonnée := faux;
ligneCurseur := 1;
colonneCurseur := 1;
chargerGrille(entE entierAléatoire(entE 1, entE NB_FICHIERS_GRILLES), sortE grilleJeu);
// Boucle principale du jeu
faire
écrireGrille(entE grilleJeu);
faire
commande := entréeCommande();
commandeRéussie := exécuterCommande(entE commande,
entE/sortE grilleJeu,
entE/sortE ligneCurseur,
entE/sortE colonneCurseur,
sortE partieAbandonnée);
tant que (NON commandeRéussie)
tant que (NON partieAbandonnée ET NON estGrilleComplète(entE grilleJeu))
// La partie n'a pas été abandonnée, elle s'est donc terminée par une victoire
si (NON partieAbandonnée) alors
écrireEcran("Bravo, vous avez gagné !");
finsi
fin
Let's translate it to C:
$ psdc c sudoku.psc -o sudoku.c
testPrograms/sudoku.psc:25.24-39: P0002: error: undefined function or procedure `entierAléatoire`
25 | chargerGrille(entE entierAléatoire(entE 1, entE NB_FICHIERS_GRILLES), sortE grilleJeu);
| ^^^^^^^^^^^^^^^
testPrograms/sudoku.psc:25.5-18: P0002: error: undefined function or procedure `chargerGrille`
25 | chargerGrille(entE entierAléatoire(entE 1, entE NB_FICHIERS_GRILLES), sortE grilleJeu);
| ^^^^^^^^^^^^^
testPrograms/sudoku.psc:25.24-39: P0002: error: undefined function or procedure `entierAléatoire`
25 | chargerGrille(entE entierAléatoire(entE 1, entE NB_FICHIERS_GRILLES), sortE grilleJeu);
| ^^^^^^^^^^^^^^^
testPrograms/sudoku.psc:38.43-60: P0002: error: undefined function or procedure `estGrilleComplète`
38 | tant que (NON partieAbandonnée ET NON estGrilleComplète(entE grilleJeu))
| ^^^^^^^^^^^^^^^^^
testPrograms/sudoku.psc:29.9-21: P0002: error: undefined function or procedure `écrireGrille`
29 | écrireGrille(entE grilleJeu);
| ^^^^^^^^^^^^
testPrograms/sudoku.psc:31.25-39: P0002: error: undefined function or procedure `entréeCommande`
31 | commande := entréeCommande();
| ^^^^^^^^^^^^^^
testPrograms/sudoku.psc:32.32-48: P0002: error: undefined function or procedure `exécuterCommande`
32 | commandeRéussie := exécuterCommande(entE commande,
| ^^^^^^^^^^^^^^^^
Compilation failed (7 errors, 0 warnings, 0 suggestions).
Oops. Looks like we got some errors. Psdc detected that the functions and procedures called aren't defined.
That doesn't prevent it from giving us meaningful output, though.
/** @file
* @brief Sudoku
* @author raphael
* @date 12/09/2024
*/
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#define N 3
#define NB_FICHIERS_GRILLES 10
#define LONGUEUR_MAX_COMMANDE 64
#define COTE_GRILLE (N * N)
typedef int t_grilleEntier[COTE_GRILLE][COTE_GRILLE];
int main() {
t_grilleEntier grilleJeu;
int ligneCurseur, colonneCurseur;
bool partieAbandonnée;
bool commandeRéussie;
char commande[LONGUEUR_MAX_COMMANDE];
partieAbandonnée = false;
ligneCurseur = 1;
colonneCurseur = 1;
chargerGrille(entierAléatoire(1, NB_FICHIERS_GRILLES), grilleJeu);
do {
écrireGrille(grilleJeu);
do {
commande = entréeCommande();
commandeRéussie = exécuterCommande(commande, grilleJeu, &ligneCurseur, &colonneCurseur, &partieAbandonnée);
} while (!commandeRéussie);
} while (!partieAbandonnée && !estGrilleComplète(grilleJeu));
if (!partieAbandonnée) {
printf("Bravo, vous avez gagné !\n");
}
return EXIT_SUCCESS;
}
And there you have it. Automated translation between Pseudocode and C.
- C
- LLVM
- C#
- CimPU
- Java
- JavaScript
- Pascal
- Perl
- PHP
- Python
- Shell
- SQL
- Formal grammar
- Alternatives
- Loops
- For
- While
- Do..While
- Repeat..Until
- Procedures
- Functions
- Structures
-
selon
- Fix syntax error handling
- Lvalues
- Constant folding for type checking and division by zero
- Optional brackets in control structures
- Benchmarks
- Brace initialization (see TD14 ex 1)
- Compiler directives
- Contextual keywords
-
finPour
keyword (equivalent tofin
but only for loops) - Escape sequences in string and character literals
- Case-insensitive boolean operators
- More static analysis
- Alternative array syntax
tableau[INDICE_DEPART..INDICE_FIN] de type;
- Numeroted control stuctures (
si1
,si2
,si3
) - File handling (low priority)
- Preprocessor
- Static assertions
- Expression/Type probing
- Modularity (
#include
) - Conditional compilation
- Configuration
- GNU-compliant message formatting
- Translations : resx, fr
- CLI (use nuget package)
- custom header
- Formatting customization
- documentation date: now, file?
- Language standard
- Tests
- Errors
- Valid code
- Documentation
- CLI
- Language tutorials
- Initial release
- Sample "real" program
- Self-hosting (rewrite in Pseudocode)
- VSCode tooling
- Debugger
- Language server
- Better syntax highlighter
- access to argc and argv
- transpile comments
- Non-null-terminated-string-proof format strings: width specifier for lengthed strings (usually useless since null-terminated, but could be useful if non null-terminated strings are used)
- Type mappings
-
réel
→float
,double
,long double
? -
entier
→short
,int
,long
? -
caractère
→char
,tchar_t
,wchar_t
?
-
- Parameter names in prototypes?
- Doxygen documentation skeleton?
-
i++
or++i
- Use count-based string functions: strncpy, strncmp...
- use
puts
instead ofprintf
where possible - anonymous block in switch cases: always, when multiple statements, never
- anonymous block in switch default: always, when multiple statements, never
- Doxygen keyword char :
\
or@