Benvingut al meu intèrpret de miniJ. En aquest document s'expliquen les decisions d'implementació adoptades per desenvolupar aquesta pràctica.
Per executar correctament el projecte, només cal executar la comanda:
makeAquesta comanda compilarà la gramàtica amb ANTLR4 i generarà els fitxers necessaris: el lexer, parser i visitor.
Per netejar els fitxers generats i mantenir només els essencials, utilitzeu:
make clean
He decidit que en comptes d'enviar-li a l'intèrpret l'arxiu sencer, primer avaluar línia per línia abans d'enviar-se-la al parser, d'aquesta manera tinc molta més llibertat per modificar línies en cas que sigui necessari (per exemple per detectar funcions).
Per la implementació al meu codi, he deixat que la gramàtica de Antlr4 identifiqui ella mateixa les funcions. Tinc el següent codi:
stat : ID '=:' simple #id
| simple #statsimple
| ID '=:' .+? #function
Això funciona de la següent manera, la gramàtica detecta les expressions que siguin formulades correctament, en aquest cas anomenades simple. Si no detecta cap expressió vàlida, dono per fet que es tracta d'una funció (.+? és qualsevor combinació de caracters), de manera que se'n va al cas final, d'assignació d'una funció.
Una vegada al codi Python, agafo el nom de la funció i, si no existia una funció amb aquest nom, afegeixo al diccionari de funcions clau amb el nom de la funció i el valor de la clau és el contingut (tot el que va després de '=:'). En cas que si existís la funció se substitueix el valor.
Seguint la recomanació del professor, he mantingut la gramàtica el més senzilla possible. Només conté tres regles principals:
-
root: això és simplement per llegir la primera linea.
-
stat: aquest node s'ha implementat amb la idea de diferenciar entre les asignacions, expresions basiques i declaració de funcions.
-
simple: aquí ja es defineixen els diferents operadors que es poden aplicar a les expresions.
Les operacions unàries i binàries no es tracten a la gramàtica, sinó directament a Python, deixant així una gramàtica minimalista i fàcil de mantenir.
Les funcions es detecten com qualsevol estructura que no sigui ni una assignació ni una expressió.
Finalment, pel tractament d'error, he decidit fer un "try" pels erros dels operadors en els quals faig servir numpy, per la resta d'erros dels operands, els he fet a mà. Per la detecció d'alguns dels erros sintàctics, com per exemple "(1 2 3", he fet servir l'import "ErrorListener" de la llibreria de antlr4, i línia per línia l'executo i comprovo si antlr4 ha trobat qualsevol error de sintaxi.
Per la divisió del codi he fet el següent, tinc l'avaluador a una classe, els operadors i les assignacions s'han incorporat a una altra classe. Finalment, el codi que s'executa és el que incorpora el main. L'estructura queda de la següent manera:
Practica /
| exprsG.py
| exprsG.g4
| clases /
| dictionaries.py
| EvalVisitor.py
| Jocs_proba /
| joc_github_basic.j
| joc_probes1.j
| joc_probes2.j
| joc_probes3.j
| joc_github_basic.out
| joc_probes1.out
| joc_probes2.out
| joc_probes3.out
| makefile
| README.md