Referencia de sintaxis y operadores
Para aprender: fundamentos, flujo, funciones, clases. Complementos: gramática, tipos.
Esta referencia describe el parser y evaluator de esta revisión. Las limitaciones observadas se indican como tales; no son propuestas de diseño.
Léxico
Las palabras reservadas se obtienen de parser.KeywordNames():
Init abstract as async break case catch class const continue default defer do echo empty
enum extends false foreach func implements instanceof interface is isset let match new nil null print private
protected public ref return select static this throw true try while yield
var, int, mixed, await y make_chan son identificadores
interpretados por contexto o nombres de funciones, no keywords del lexer.
Las constantes internas IF y ELSE no significan que esas construcciones
estén disponibles. if, else, elif, for y switch no son
estructuras fuente de Joss.
| Forma | Regla |
|---|---|
| Identificador | ASCII: letras, _ o @ al inicio; también dígitos después. Evita @ fuera de APIs concretas; no es un sistema de anotaciones. |
| Variable | $nombre; el token $ se separa del nombre. $this tiene tratamiento propio. |
| Comentarios | // y # hasta fin de línea; /* ... */ sin anidamiento. |
| Strings | Comillas simples o dobles; escapes \n, \t, \r, \', \", \\; interpolación estilo Dart/Flutter en comillas dobles: "${var}" o "${expr}" (escape \${); comillas simples sin interpolación. |
| Enteros | Secuencia de dígitos; el parser usa base automática: 010 se lee como octal, 08 falla. Evita ceros iniciales. |
| Float | Dígitos, punto y más dígitos: 0.5. No hay literal exponencial, hexadecimal ni separador _ en el lexer. |
| Decimal | Entero o fracción con sufijo m/M: 100m, 1.25M. |
| Ausencia | null y nil producen el mismo valor. |
| Separación | Nueva línea o ;. Los espacios y tabs no delimitan bloques. |
El lexer elimina BOM UTF-8 inicial. Fuera de strings, omite bytes no ASCII: no confíes en identificadores acentuados. Los diagnósticos de strings multilínea y texto no ASCII aún tienen limitaciones de posición.
Además de nombres, literales y keywords, se tokenizan:
= += -= *= /= ??= + - ! * / % < > == != === !== <=> <= >= << >> && || ++ --
, ; : ? ( ) { } [ ] . .. ... -> ?-> :: | |> ?? =>
NEWLINE EOF ILLEGAL
No hay exponenciación, AND binario & ni OR binario |;
este último separa tipos de una unión.
Precedencia: de menor a mayor
La tabla reproduce pkg/parser/parser.go. A igual nivel, los infijos
ordinarios agrupan a la izquierda; la asignación analiza toda su derecha.
| Nivel | Operadores / construcciones |
|---|---|
| 1 | =, +=, -=, *=, /=, ??= (derecha) |
| 2 | ? :, ?: |
| 3 | ?? |
| 4 | &&, \|\| |
| 5 | ==, !=, ===, !==, <=> |
| 6 | <, >, <=, >=, .., is, instanceof |
| 7 | \|> |
| 8 | +, -, . |
| 9 | <<, >> |
| 10 | *, / |
| 11 | % |
| 12 | Prefijos -, !, ref, ... |
| 13 | Llamada () |
| 14 | Índice [], miembros ->, ?->, ::, postfix ++, -- |
Consecuencias: % liga más fuerte que multiplicación y división, mientras
&& y || comparten nivel. Usa paréntesis para expresar tu intención.
Los brazos del ternario se parsean como expresiones completas; parentetiza
ternarios anidados en vez de trasladar la asociatividad de otro lenguaje.
print(8 * 5 % 3)
print(true || false && false)
print(true || (false && false))
Da 16, false y true. La primera expresión es 8 * (5 % 3).
No es una tabla de precedencia de PHP o Go.
Evaluación
+,-,*: enteros exactos con overflow comprobado; promoción si hay float, operaciones decimales si interviene decimal./: resultado float para enteros; decimal si interviene decimal.+=,-=,*=,/=,??=: asignación compuesta y asignación nula coalescente ($a ??= $bequivale a$a = $a ?? $b) con validación estricta de tipos.%: resto entero; con float trunca operandos a entero; decimal usaMod..: representa operandos como texto y concatena;nullcontribuye texto vacío...: operador de rango numérico ($a..$b); genera una secuencia entera entre ambos límites, útil en expresiones y buclesforeach (1..10 as $i)."${...}": interpolación de cadenas estilo Flutter / Dart dentro de comillas dobles. Permite incrustar variables o expresiones (ej."${indice}","${a + b}"), desazucarándose automáticamente a concatenaciones de tipo string. El escape\${imprime${de forma literal.++,--: incrementa o decrementa la variable numérica y retorna el valor anterior.&&,||: cortocircuito y resultado bool.!: negación de truthiness.==/!=: comparación numérica cuando corresponde; fallback mediante representación textual para otros valores. Para colecciones prefiere===/!==, basados en comparación estructural.===: distingue entero, float, string y decimal; normaliza variantes numéricas internas de Go antes de comparar.<=>: retorna-1,0o1; compara números, strings, nulos y finalmente representaciones textuales.??: evalúa la derecha sólo si la izquierda es nula. Actualmente recupera cualquier panic de la izquierda y lo trata como nulo.?:(Elvis): conserva la izquierda si es verdadera según truthiness.- Ternario completo y de una sola rama:
cond ? expr : expry(cond) ? { cuerpo }(permite omitir la rama: {}cuando no se requiere alternativa falsa). match: selección múltiple por valor; admite expresiones o bloques multilínea{ ... }.?->: devuelve nulo ante receptor nulo; no valida ni corrige otros accesos.|>: antepone el valor izquierdo a los argumentos de una función, llamada o closure.cout << valor: imprime sin agregar salto y retornacout.canal << valor: envía al canal.cin >> $variable: lee de forma adaptativa desde la entrada estándar (convirtiendo automáticamente a número si la variable o entrada es numérica y leyendo líneas completas con espacios si es texto).
Verdad de valores
isFalsy considera falsos: null, false, int64(0), decimal cero,
"", "0" y array vacío. Considera verdaderas las instancias.
El caso float cero y el mapa vacío no se comprueban y resultan verdaderos.
Por eso conviene escribir condiciones bool explícitas. empty usa esa misma
interpretación tras comprobar existencia, no una regla universal de «sin datos».
Declaraciones y ámbitos
| Forma | Efecto |
|---|---|
$x = valor |
Primera asignación declara/infiere; después reasigna. |
var $x = valor |
Declaración con inferencia fija. |
T $x = valor, let T $x = valor |
Tipo explícito. |
let $x = valor, mixed $x = valor |
Binding dinámico explícito. |
const [T] $x = valor |
Binding constante; requiere inicializador. |
int $a = 1, $b = 2 |
Declaración múltiple del mismo tipo. |
public/private func f(T $p): R { ... } |
Función global; retorno opcional, parámetros tipados. |
func(T $p): R { ... } |
Closure sin modificador de visibilidad. |
public/private class C [extends B] [implements I1, I2] { ... } |
Clase; superclase opcional e interfaces implementadas. |
public/private interface I [extends I1, I2] { ... } |
Interfaz; contratos de métodos públicos sin cuerpo. |
Init nombre(...) { ... } |
Inicializador sin modificador. |
Las funciones/clases globales se registran antes de analizar cuerpos. Las variables de nivel superior no son globals implícitos de funciones con nombre. Cada llamada usa su frame; una closure captura un entorno. La visibilidad de métodos y propiedades es obligatoria. No hay sobrecargas por firma ni sintaxis general de parámetros de tipo.
Bloques, colecciones y sentencias
[] crea un array, {} crea un map vacío en contexto de expresión y
{"clave": valor} crea un map no vacío. Una llave en un lugar que exige un
cuerpo (función/ciclo) delimita un bloque. Los bloques como expresiones se
representan internamente como AST y no se ejecutan automáticamente en todo contexto.
- Ternario: elige un valor o ejecuta el bloque seleccionado;
returnpuede salir del callable desde ese bloque. while (condición) { ... }: comprueba antes de cada vuelta.do { ... } while (condición): comprueba después.foreach (array_o_canal as $valor)oforeach ($coleccion as $clave => $valor): recorre secuencias, rangos1..$n, mapas asociativos y canales de concurrencia.breakycontinue: salir/saltar vuelta.defer { ... }odefer expresión;: pospone la ejecución de la sentencia hasta que el frame actual finalice (en orden LIFO).[$a, $b] = $expr: destructuración secuencial de arreglos en asignación directa.match (valor) { clave, clave => resultado, default => resultado }: compara estrictamente, primer brazo coincidente; sin coincidencia/default retorna nulo.try { ... } catch ($error) { ... },throw expresión: recuperación runtime.return [expresión]: sale del callable.async { ... }: crea un Future; se recoge conawait(futuro).Console::*: módulo nativo para colores ANSI (Console::green,Console::red,Console::bold, etc.).joss repl: entorno interactivo por terminal (Read-Eval-Print Loop).
Ausencias y compatibilidad
No hay imports fuente, namespaces, exports de archivos, interfaces, traits,
protocolos, ownership, punteros manuales, switch, for clásico ni syntax sugar de funciones flecha.
ref sólo sirve como parámetro/argumento temporal y no es un puntero almacenable.
function, import, @import, use, Use, Import,
namespace y Namespace generan errores de sintaxis eliminada.
Los nombres heredados de APIs no son necesariamente tipos fuente válidos:
is_integer sigue registrado, integer $x no es alias de int.