Índice de entradas del conversor
Modificado el 12/03/2026, ampliaciones en color rojo
📘 Tabla de Contenidos
- Introducción
- 1. Estructura de un programa
- 2. Tipos de datos
- 3. Expresiones
- 4. Sentencias
- 5. Control de flujo
- 6. Datos
- 7. Comentarios
- 8. Funciones incorporadas
- 9. Arrays
- 10. Gráficos
- 11. Colores
- 12. Sonido
- 13. Cinta y ficheros
- 14. Gramática mínima para transpiladores
- 15. BNF/EBNF formal (48K)
- 16. Referencias
Gramática del ZX BASIC del Spectrum 48K
Esta entrada ofrece un resumen estructurado de la gramática del ZX BASIC del Sinclair ZX Spectrum 48K, basado en las referencias originales del manual oficial del Spectrum y las versiones digitalizadas del manual en español. Primero se presenta una versión ligera y, después, la definición formal completa.
- BNF/EBNF práctica, apta para implementar (recursive descent o LL(1) con pequeñas adaptaciones).
- Las restricciones del hardware (p. ej. rango de números de línea) se indican en comentarios.
- Se prioriza claridad en la introducción; los detalles formales aparecen en el BNF completo final.
NOTA IMPORTANTE: heredado de los ZX80/81 con solo 1 KB disponible, para ahorrar memoria todas las palabras clave se almacenan internamente como tokens de 1 byte. Por tanto, toda sentencia debe comenzar obligatoriamente por un token de palabra clave. No puede comenzar por un identificador. LET es obligatorio siempre. REM solo se reconoce si es exactamente REM.
Estos ajustes son mínimos pero críticos para definir correctamente la gramática y la generación de tokens.
1. Estructura de un programa
Un programa en ZX BASIC está compuesto por líneas numeradas:
<linea> ::= <numero> <espacio> <instruccion>
- Los números de línea van de 1 a 9999.
- Una línea puede contener una o varias instrucciones separadas por
:.
2. Tipos de datos
2.1 Tipos básicos
- Números: coma flotante de 40 bits.
- Cadenas: delimitadas por comillas (
"texto"). - No existen enteros ni booleanos como tipos nativos; la lógica usa 0 para falso y <>0 para cierto.
2.2 Nombres de variables
<var_num> ::= <letra> [ <letra_o_digito> ]
<var_str> ::= <letra> [ <letra_o_digito> ] "$"
<var_array> ::= <var> "(" <lista_expresiones> ")"
- Las variables numéricas y de cadena con el mismo nombre son distintas.
- Las matrices pueden ser numéricas o de cadena.
3. Expresiones
3.1 Expresiones numéricas
Precedencia de operadores (de mayor a menor):
- Unario:
- - Potencia:
^ - Multiplicación / División:
*/ - Suma / Resta:
+- - Relacionales:
=,<,>,<=,>=,<> - Lógicos:
AND,OR,NOT
Fuentes: capítulos 3, 7 y 13 del manual.
3.2 Expresiones de cadena
- Concatenación:
"A" + "B". - Slicing:
A$(n TO m). - Longitud:
LEN A$.
Fuente: capítulo 8 del manual.
4. Sentencias
4.1 Asignación
<asignacion> ::= LET <var> = <expresion>
LET es obligatorio en el Spectrum 48K (no puede omitirse).
4.2 Entrada y salida
PRINTINPUTCLSTAB(n),AT y,x
Fuente: capítulos 2 y 15 del manual.
5. Control de flujo
5.1 IF
IF <expresión> THEN <instrucciones>
Ejecuta todas las instrucciones (separadas por :) hasta fin de línea.
No existe ELSE en el ZX Spectrum 48K.
5.2 Bucles FOR
FOR <var> = <expr> TO <expr> [STEP <expr>] ... NEXT <var>
Fuente: capítulo 4 del manual.
5.3 Subrutinas
GOSUB número RETURN
Fuente: capítulo 5 del manual.
5.4 Saltos
GO TOSTOPCONTINUE
6. Datos
READ <lista_variables> DATA <lista_constantes> RESTORE [número]
Fuente: capítulo 6 del manual.
7. Comentarios
En ZX Spectrum 48K, la sentencia REM admite exactamente dos formas:
- Comentario vacío:
REMseguido inmediatamente de fin de línea. - Comentario con contenido:
REMseguido de un ESPACIO y, a continuación, cualquier número de caracteres (incluidos espacios) hasta fin de línea.
Ejemplos válidos:
10 REM
20 REM Hola mundo
30 REM Más espacios al inicio del comentario
Ejemplos inválidos:
40 REMHola ; falta el espacio tras REM
50 REMHola ; tabulación inmediata tras REM (no permitido)
EBNF:
ESPACIO = " ";
EOL = "\n";
anyCharacter = ? cualquier carácter Unicode ? ;
remStmt =
"REM"
| "REM" , ESPACIO , { anyCharacter } ;
8. Funciones incorporadas
Matemáticas
ABS, INT, SGN, SIN, COS, TAN, ASN, ACS, ATN, SQR, EXP, LN, PI …
Cadenas
LEN, STR$, VAL, CHR$, CODE
Sistema
PEEK, POKE, USR, IN, OUT, RND, RANDOMIZE
Fuente: capítulos 9, 10, 11, 14 y 23 del manual.
9. Arrays
DIM A(10) DIM N$(5)
- Índices desde 1 hasta el tamaño declarado (arrays base 1).
- Acceso:
A(1), A(5), N$(1)…
10. Gráficos
PLOT x,yDRAW dx,dyCIRCLE x,y,rPOINT x,y
Fuente: capítulo 17 del manual.
11. Colores
INK nPAPER nFLASH nBRIGHT nINVERSE nOVER nBORDER n
Fuente: capítulo 16 del manual.
12. Sonido
BEEP duracion, tono
Fuente: capítulo 19 del manual.
13. Cinta y ficheros
SAVELOADMERGEVERIFY
Fuente: capítulo 20 del manual.
14. Gramática mínima para transpiladores
<program> ::= { <line> }
<line> ::= <number> <Statement>
<Statement> ::= <SimpleStatement> { ":" <SimpleStatement> }
<SimpleStatement> ::= <assign>
| PRINT <print_list>
| INPUT <var_list>
| IF <expr> THEN <Statement>
| FOR <assign> TO <expr> ["STEP" <expr>]
| NEXT <var>
| GOSUB <number>
| RETURN
| GO TO <number>
| READ <var_list>
| DATA <const_list>
| DIM <dim_list>
| PLOT | DRAW | CIRCLE | POINT | ...
15. BNF/EBNF del ZX BASIC del Spectrum 48K (versión corregida)
1) Léxico
letter = "A".."Z" | "a".."z" digit = "0".."9" nonZeroDigit = "1".."9" alnum = letter | digit numVar = letter , [ alnum ] strVar = letter , [ alnum ] , "$" var = numVar | strVar intLiteral = digit , { digit } fractPart = "." , { digit } expPart = ("E" | "e") , [ "+" | "-" ] , digit , { digit } numLiteral = intLiteral , [ fractPart ] , [ expPart ] | fractPart , [ expPart ] ESPACIO = " " EOL = "\n" anyCharacter = ? cualquier carácter Unicode ? strLiteral = '"' , { anyCharacter } , '"' ; REM solo se reconoce como palabra clave si el token es exactamente "REM". ; Un identificador NO puede iniciar una sentencia.
2) Estructura del programa
program = { line }
line = lineNumber , Statement
lineNumber = LineNumberToken
LineNumberToken = nonZeroDigit , [ digit ] , [ digit ] , [ digit ]
(* Rango efectivo: 1..9999; token específico generado por el lexer *)
3) Statement y SimpleStatement
Statement = SimpleStatement , { ":" , SimpleStatement }
; SimpleStatement debe comenzar por token de palabra reservada
SimpleStatement =
letStmt
| printStmt
| inputStmt
| ifStmt
| forStmt
| nextStmt
| gotoStmt
| gosubStmt
| returnStmt
| stopStmt
| continueStmt
| readStmt
| dataStmt
| restoreStmt
| dimStmt
| clsStmt
| graphicStmt
| colorStmt
| soundStmt
| tapeStmt
| remStmt
4) Expresiones
expr = logicOr
logicOr = logicAnd , { "OR" , logicAnd }
logicAnd = relation , { "AND" , relation }
relation = arithExpr , [ relOp , arithExpr ]
relOp = "=" | "<>" | "<" | ">" | "<=" | ">="
arithExpr = term , { ("+" | "-") , term }
term = power , { ("*" | "/") , power }
power = unary , { "^" , unary }
unary = [ "-" | "NOT" ] , primary
primary = numLiteral
| strLiteral
| varRef
| funcCall
| "(" , expr , ")"
5) Variables y arrays (base 1)
varRef = arrayRef | var
arrayRef = ( numVar | strVar ) ,
"(" , indexExpr , { "," , indexExpr } , ")"
indexExpr = expr
6) Funciones
funcCall = funcNum | funcStr | sysFunc
funcNum = ("ABS" | "INT" | "SGN" | "SIN" | "COS" | "TAN"
| "ASN" | "ACS" | "ATN" | "SQR" | "EXP" | "LN"
| "VAL" | "PI")
"(" , [ expr ] , ")"
funcStr = "LEN" "(" , ( strVar | strLiteral ) , ")"
| "STR$" "(" , expr , ")"
| "CHR$" "(" , expr , ")"
sysFunc = "PEEK" "(" , expr , ")"
| "USR" "(" , expr , ")"
| "CODE" "(" , (strVar | strLiteral) , ")"
7) Sentencias (detalle)
remStmt = "REM"
| "REM" , ESPACIO , { anyCharacter }
letStmt = "LET" , ( varRef | var ) , "=" , exprprintStmt = "PRINT" , [ printList ]
printList = printItem , { ("," | ";") , printItem }
printItem = expr
| "TAB" "(" , expr , ")"
| "AT" expr "," expr
inputStmt = "INPUT" , varList
varList = varRef , { "," , varRef }
ifStmt = "IF" , expr , "THEN" , Statement
forStmt = "FOR" , numVar , "=" , expr , "TO" , expr , [ "STEP" , expr ]
nextStmt = "NEXT" , [ numVar ]
gotoStmt = ("GOTO" | "GO TO") , lineNumber
gosubStmt = ("GOSUB" | "GO SUB") , lineNumber
returnStmt= "RETURN"
stopStmt = "STOP"
continueStmt = "CONTINUE"
readStmt = "READ" , varList
dataStmt = "DATA" , constList
constList = constItem , { "," , constItem }
constItem = numLiteral | strLiteral
restoreStmt = "RESTORE" , [ lineNumber ]
dimStmt = "DIM" , dimList
dimList = dimItem , { "," , dimItem }
dimItem = ( numVar | strVar ) , "(" , sizeExpr , { "," , sizeExpr } , ")"
sizeExpr = expr
clsStmt = "CLS"
graphicStmt = plotStmt | drawStmt | circleStmt | pointStmt
plotStmt = "PLOT" , expr , "," , expr
drawStmt = "DRAW" , expr , "," , expr
circleStmt= "CIRCLE" , expr , "," , expr , "," , expr
pointStmt = "POINT" , expr , "," , expr
colorStmt = ("INK" | "PAPER" | "FLASH" | "BRIGHT" | "INVERSE" | "OVER" | "BORDER") , expr
soundStmt = "BEEP" , expr , "," , expr
tapeStmt = ("SAVE" | "LOAD" | "VERIFY" | "MERGE") , strLiteral
16. Referencias
- Manual canónico (World of Spectrum) — Índice completo del ZX Spectrum BASIC Programming Manual (Sinclair/Amstrad). https://worldofspectrum.org/ZXBasicManual/
- World of Spectrum — Capítulo 13: Conditions — Operadores lógicos y prioridad (AND/OR/NOT, relacionales). https://worldofspectrum.org/ZXBasicManual/zxmanchap13.html
-
Introducción Sinclair (Statement LET) — Especifica que en 48K
LETno puede omitirse. https://worldofspectrum.org/ZXSpectrumIntroduction/chapter_five.html - Manual de Investrónica (español) — Edición en HTML con capítulos de cadenas, matrices, gráficos y colores (consulta rápida). https://manuales.speccy.org/basic_gomas/












