/* Jerarquía de Expresiones (Precedencia de menor a mayor) */
<expression>       ::= <logical_or>
<logical_or>       ::= <logical_and> ( "or" <logical_and> )*
<logical_and>      ::= <logical_not> ( "and" <logical_not> )*
<logical_not>      ::= "not" <logical_not> | <comparison>

<comparison>       ::= <arithmetic> ( <comp_op> <arithmetic> )*
<comp_op>          ::= "==" | "!=" | "<" | ">" | "<=" | ">=" | "in" | "is"

<arithmetic>       ::= <term> ( ( "+" | "-" ) <term> )*
<term>             ::= <factor> ( ( "*" | "/" | "%" ) <factor> )*
<factor>           ::= ( "+" | "-" ) <factor> | <power>
<power>            ::= <primary> [ "**" <factor> ]

/* Primarios y Átomos (Accesos, Castings, Slicing, Métodos y Funciones)
   La regla <primary> cubre también el acceso a métodos de objetos conector
   (conector.metodo(...)) y el acceso por clave a sus resultados (resultado["key"]) */
<primary>          ::= <atom>
                     | <primary> "." <identifier>
                     | <primary> "[" <expression> "]"
                     | <primary> "[" [<expression>] ":" [<expression>] [":" [<expression>]] "]"
                     | <primary> "(" [<argument_list>] ")"

<atom>             ::= <identifier>
                     | "$" <identifier>
                     | <literal>
                     | "(" <expression> ")"
                     | <list_display>
                     | <dict_display>

/* Estructuras de Datos, Comprensiones y Argumentos */
<list_display>     ::= "[" [<argument_list>] "]"
                     | "[" <expression> "for" <identifier> "in" <expression> [<if_clause>] "]"
<if_clause>        ::= "if" <expression>
<dict_display>     ::= "{" [<key_datum_list>] "}"
<key_datum_list>   ::= <key_datum> ( "," <key_datum> )*
<key_datum>        ::= <expression> ":" <expression>
<argument_list>    ::= <expression> ( "," <expression> )*

/* Tipo numérico unificado */
<number>           ::= <floatnumber> | <integer>

/* Literales (Tipos de Datos Primitivos Soportados) */
<literal>          ::= <stringliteral> | <number> | <boolean> | "None"
<boolean>          ::= "True" | "False"
<integer>          ::= [0-9]+
<floatnumber>      ::= [0-9]+ "." [0-9]* | "." [0-9]+

/* Cadenas de Texto con soporte de secuencias de escape */
<stringliteral>    ::= "\"" <text_double> "\"" | "'" <text_single> "'"
<escape_sequence>  ::= "\\" ( "\"" | "'" | "\\" | "n" | "t" | "r" | "0" )
<text_double>      ::= ( [^"\\] | <escape_sequence> )*
<text_single>      ::= ( [^'\\] | <escape_sequence> )*
<identifier_or_string> ::= <identifier> | <stringliteral>

/* Reglas de Comentarios para el Lexer
   El lexer aplica longest-match: /// debe evaluarse ANTES que // */
<doc_comment>      ::= "///" <any_text>
<line_comment>     ::= "//" <any_text>
<block_comment>    ::= "/*" <any_content> "*/"
<any_text>         ::= [^\r\n]*
<any_content>      ::= /* Cualquier secuencia de caracteres que no contenga la subcadena "*/" */