Descargar

Gramática

La sintaxis completa de HyperEZ en notación EBNF. { x } significa "cero o más veces", [ x ] "opcional" y | "o". Los textos entre comillas son literales. NL es un salto de línea (o ;), que termina las sentencias.

Es una referencia para quien quiera escribir herramientas o entender el parser (src/lang/syntax/parser.cpp); para aprender, es mejor la referencia por temas.

Programa y sentencias

programa      = { sentencia NL } ;
bloque        = "{" { sentencia NL } "}" ;

sentencia     = declaracion | if | while | do_while | for | foreach | repeat | try | match
              | "return" [ expresion ] | "break" | "continue" | "throw" expresion
              | emit | on | expresion ;

declaracion   = [ visibilidad ] ( variable | funcion | clase | interfaz | enum | evento )
              | importacion ;
visibilidad   = "private" | "public" | "protected" ;

Declaraciones

variable      = ( "var" | "let" | "const" ) ( NOMBRE [ ":" tipo ] [ "=" expresion ]
                                            | patron "=" expresion ) ;
patron        = "[" [ elemento { "," elemento } ] "]"
              | "{" [ campo { "," campo } ] "}" ;
elemento      = [ "..." ] NOMBRE ;
campo         = NOMBRE [ ":" NOMBRE ] ;

funcion       = [ "async" ] "function" NOMBRE parametros [ ":" tipo ] bloque ;
parametros    = "(" [ parametro { "," parametro } ] ")" ;
parametro     = [ "..." ] NOMBRE [ ":" tipo ] [ "=" expresion ] ;

clase         = ( "class" | "struct" ) NOMBRE [ "extends" NOMBRE ] [ "implements" NOMBRE { "," NOMBRE } ]
                "{" { miembro NL } "}" ;
miembro       = [ visibilidad ] [ "static" ] ( variable | metodo | acceso | constructor ) ;
metodo        = [ "async" ] "function" NOMBRE parametros [ ":" tipo ] bloque ;
acceso        = ( "get" NOMBRE "(" ")" | "set" NOMBRE "(" parametro ")" ) [ ":" tipo ] bloque ;
constructor   = "constructor" parametros bloque ;

interfaz      = "interface" NOMBRE [ "extends" NOMBRE { "," NOMBRE } ]
                "{" { "function" NOMBRE parametros [ ":" tipo ] NL } "}" ;
enum          = "enum" NOMBRE "{" [ valorEnum { "," valorEnum } ] "}" ;
valorEnum     = NOMBRE [ "=" ( NUMERO | TEXTO ) ] ;
evento        = "event" NOMBRE parametros ;

importacion   = "import" ( TEXTO | ruta ) [ "as" NOMBRE ]
              | "from" ( TEXTO | ruta ) "import" NOMBRE [ "as" NOMBRE ] { "," NOMBRE [ "as" NOMBRE ] } ;
ruta          = NOMBRE { "." NOMBRE } ;

tipo          = ( NOMBRE [ "<" tipo { "," tipo } ">" ] | "(" [ tipo { "," tipo } ] ")" "=>" tipo ) [ "?" ] ;

Control del flujo

if            = "if" expresion bloque [ "else" ( if | bloque ) ] ;
while         = "while" expresion bloque ;
do_while      = "do" bloque "while" expresion ;           (* "do" solo es especial delante de '{' *)
for           = "for" NOMBRE [ "," NOMBRE ] "in" expresion [ "step" expresion ] bloque ;
foreach       = "foreach" NOMBRE [ "," NOMBRE ] "in" expresion bloque ;
repeat        = "repeat" expresion bloque ;
try           = "try" bloque [ "catch" [ NOMBRE ] bloque ] [ "finally" bloque ] ;

match         = "match" expresion "{" { caso NL } "}" ;
caso          = ( patrones [ "if" expresion ] | "else" [ "if" expresion ] ) "=>" ( expresion | bloque ) ;
patrones      = expresion { "," expresion } ;

emit          = "emit" expresion argumentos ;
on            = ( "on" | "once" ) expresion [ "priority" expresion ] [ "as" NOMBRE ] bloque ;

Expresiones (de menor a mayor precedencia)

expresion     = asignacion ;
asignacion    = tuberia [ ( "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "**=" | "??=" ) asignacion ] ;
tuberia       = condicional { "|>" condicional } ;      (* a |> f(x) es f(a, x) *)
condicional   = nulo [ "?" expresion ":" expresion ] ;
nulo          = o { "??" o } ;
o             = y { "or" y } ;
y             = no { "and" no } ;
no            = "not" no | igualdad ;
igualdad      = comparacion { ( "==" | "!=" ) comparacion } ;
comparacion   = bitOr { ( "<" | "<=" | ">" | ">=" | "in" | "not" "in" ) bitOr | "is" [ "not" ] tipo } ;
bitOr         = bitXor { "|" bitXor } ;
bitXor        = bitAnd { "^" bitAnd } ;
bitAnd        = desplaz { "&" desplaz } ;
desplaz       = rango { ( "<<" | ">>" ) rango } ;
rango         = suma [ ( ".." | "..=" ) suma ] ;
suma          = producto { ( "+" | "-" ) producto } ;
producto      = unario { ( "*" | "/" | "%" ) unario } ;
unario        = ( "-" | "+" | "!" | "~" | "++" | "--" | "await" ) unario | potencia ;
potencia      = postfijo [ "**" unario ] ;
postfijo      = primario { "." NOMBRE | "?." NOMBRE | "[" indice "]" | "?.[" indice "]"
                         | argumentos | "++" | "--" } ;
argumentos    = "(" [ argumento { "," argumento } ] ")" ;
argumento     = [ NOMBRE ":" ] expresion | "..." expresion ;
indice        = expresion | [ expresion ] ( ".." | "..=" ) [ expresion ] ;   (* lista[2..], texto[..3] *)

primario      = NUMERO | TEXTO | "true" | "false" | "null" | "this" | "super" "." NOMBRE
              | NOMBRE | "(" expresion ")" | lista | mapa | lambda | match ;
lista         = "[" [ [ "..." ] expresion { "," [ "..." ] expresion } [ "," ] ] "]"
              | "[" expresion comprension "]" ;
mapa          = "{" [ entrada { "," entrada } [ "," ] ] "}"
              | "{" clave ":" expresion comprension "}" ;
entrada       = clave ":" expresion | "..." expresion ;
comprension   = "for" NOMBRE [ "," NOMBRE ] "in" expresion [ "step" expresion ] [ "if" expresion ] ;
clave         = NOMBRE | TEXTO | "[" expresion "]" ;
lambda        = [ "async" ] ( NOMBRE | parametros [ ":" tipo ] ) "=>" ( expresion | bloque ) ;

Elementos léxicos

NOMBRE        = letra { letra | digito } ;          (* letra incluye "_", acentos y ñ *)
NUMERO        = digitos [ "." digitos ] [ ( "e" | "E" ) [ "+" | "-" ] digitos ]
              | "0x" hex { hex } | "0b" ( "0" | "1" ) { "0" | "1" } | "0o" octal { octal } ;
digitos       = digito { digito | "_" } ;
TEXTO         = '"' { caracter | escape | interpolacion } '"'
              | "'" { caracter | escape | interpolacion } "'"
              | '"""' { cualquiera } '"""'
              | "r" '"' { cualquiera } '"' | "r" "'" { cualquiera } "'" ;
interpolacion = "${" expresion [ ":" formato ] "}" ;
formato       = [ [ relleno ] ( "<" | ">" | "^" ) ] [ "+" ] [ "0" ] [ digitos ] [ "," | "_" ] [ "." digitos ]
                [ "f" | "e" | "E" | "%" | "d" | "x" | "X" | "b" | "o" | "s" ] ;
escape        = "\n" | "\t" | "\r" | "\0" | "\\" | '\"' | "\'" | "\$" | "\u{" hex { hex } "}" ;
comentario    = "//" { cualquiera } fin_de_linea | "/*" { cualquiera } "*/" ;