dijous, 22 d’abril del 2021

JailScript (III): Lexemes, Gramàtiques i Contextos

Aquest es el tercer escrit d’una sèrie que repassarà el desenvolupament d’un llenguatge de programació amb el qual poder fer JailGames de forma ràpida i còmoda. En aquest post vorem una descripció pseudo-formal del llenguatge.

Nivell lèxic

A nivell lèxic, el llenguatge distingirà entre tres tipus genèrics de paraula:

  • Numèrics: 1 o més dígits, seguits opcionalment per un punt "." i 1 o mes dígits.
  • Alfanumèrics: Una lletra o "_", opcionalment seguida de lletra, dígit o "_".
  • Cadenes: doble cometa (") fins a la següent doble cometa.
  • Símbols: Operadors del tipus "=", ",", "+", "<=" o inclús "\n".

Els numèrics sempre seran constants numèriques i ja està. Però els alfanumèrics poden ser paraules clau del llenguatge (IF, ELSE...), tipus de dades (NUMBER, STRING o els que defineixca l’usuari), funcions (internes o externes) o variables. Les cadenes agafen qualsevol caràcter que hi haja entre les dobles cometes. Per últim, si no es numèric, alfanumèric o cadena, es comprovarà si es un dels operadors (matemàtics, lògics, de control...) coneguts pel llenguatge. En cas contrari, tindrem un error de sintaxi.

Gramàtica

Vaig a expressar la gramàtica del llenguatge, o siga les frases vàlides, en una espècie de pseudo forma de Backus-Naur, però sense crear realment regles de producció. Es un poc rotllo així que passe de liar. Pero abans de vomitar-les totes, un poquet d’explicació amb un exemple:

ASSIGNSTAT = <ID_VAR> = <EXPR>

Espera... que cony es això? Explique: Vaig a definir una assignació de valor a una variable, bàsicament açò:

peric = delgat + 3

“ASSIGNSTAT” es el nom d’esta regla o frase. “ID_VAR” representa a una paraula alfanumèrica asociada a una variable ja declarada abans (en el exemple, “peric”). “=” se representa a si mateix. <EXPR> representa a una expressió, o siga, una combinació de operacions matemàtiques i lògiques entre constants, variables i resultats de funcions que donarà com a resultat un valor (en l’exemple “delgat + 3”).

STRUCTSTAT = STRUCT <UNK> [ <UNK> AS <TYPE> ]+ END
FUNSTAT = FUNCTION <UNK> ( [ <UNK> AS <TYPE> [ , <UNK> AS <TYPE> ]* ) [ AS <TYPE> ] <LOCAL> END
VARSTAT = VAR <UNK> AS [ ARRAY OF <NUM> ] <TYPE> [ = <EXPR> ]
CONSTSTAT = CONST <UNK> = <EXPR>
ASSIGNSTAT = <ID_VAR> = <EXPR>
CALLSTAT = <ID_FUN> ( [ <EXPR> [ , <EXPR> ]* ] )
IFSTAT = IF <EXPR> THEN <LOCAL> [ ELSE <LOCAL> ] END
WHILESTAT = WHILE <EXPR> DO <LOCAL> END
REPEATSTAT = REPEAT <LOCAL> UNTIL <EXPR>
FORSTAT = FOR <UNK> = <EXPR> TO <EXPR> [ STEP <EXPR> ] DO <LOCAL> END
RETURNSTAT = RETURN [ <EXPR> ]

<UNK> es refereix a un identificador que no s’haja definit encara en el àmbit actual.

<TYPE> es refereix a un tipus que ja s’haja declarat.

<ID_VAR> i <ID_FUN> es refereixen a identificadors assignats a una variable i a una funció.

<EXPR> es refereix a una expressió, tindrem un capítol nomes per a les expressions més avant.

<LOCAL> es refereix a un context, ara ho vorem.

Contextos

Hi ha dos tipus de context definits: Global i local. El context global es el que hi ha a la part mes externa del programa. En eixe context nomes podem declarar variable, constants, estructures i implementar funcions.

GLOBAL = [ VARSTAT | CONSTSTAT | STRUCTSTAT | FUNSTAT ]*

Als contextos locals (que es corresponen als elements <LOCAL> de les gramàtiques anteriors) no es poden declarar estructures ni implementar funcions, però poden aparèixer totes les demes regles.

LOCAL = [ VARSTAT | CONSTSTAT | ASSIGNSTAT | CALLSTAT | IFSTAT | WHILESTAT | REPEATSTAT | FORSTAT | RETURNSTAT ]*

Àmbits

Les variables es declaren a un cert àmbit. Les variables declarades al context global tenen l’àmbit més ample, al poder ser accedides des de qualsevol context (el que coneguem com a “variables globals”).

Per altra part, les variables declarades dins d’un context local nomes podran ser accedides des d’eixe context i els contextos interns. Per exemple, si tenim una funció i dins d’ella declarem una variable “teib”. I a més dins de la funció tenim després un “if”, i dins del “if” declarem una variable “peiv”. Des de dins del “if” podem accedit tant a “teib” com a “peiv”, però desde la funció, fora del “if”, tant abans com després, no podrem vore “peiv”.

Els contextos i els àmbits es corresponen quasi totalment, excepte per les següents excepcions:

  • Els paràmetres de una funció formen part de l’àmbit del context <LOCAL> de dins de la funció.
  • La variable d'iteració d’un bucle FOR forma part de l’àmbit del context <LOCAL> de dins del FOR.

A més, STRUCT crea una especie d’àmbit “privat”.

Si re-declarem una variable ja declarada en un àmbit pare, la nova variable ocultarà a l’anterior, no havent forma de accedir a l’anterior des de l’àmbit actual. El compilador soltarà un “warning” quan ho detecte. Obviament, açò no afecta als STRUCTs.


Que rollo! En el pròxim post canviaré un poc el focus i parlaré de la màquina virtual.

Cap comentari:

Publica un comentari a l'entrada