hispano-lang 1.1.7 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +672 -237
- package/dist/evaluator.js +1390 -261
- package/dist/parser.js +758 -201
- package/dist/tokenizer.js +202 -121
- package/package.json +12 -3
package/README.md
CHANGED
|
@@ -1,41 +1,106 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/nicvazquezdev/hispano-lang-website/main/public/hl-main-logo.png" alt="HispanoLang" width="180"/>
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<strong>El lenguaje de programación en español</strong>
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
Un lenguaje de programación moderno, expresivo y completamente en español.<br/>
|
|
11
|
+
Diseñado para eliminar las barreras del idioma en la educación tecnológica.
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
<p align="center">
|
|
15
|
+
<a href="https://www.npmjs.com/package/hispano-lang"><img src="https://img.shields.io/npm/v/hispano-lang?style=for-the-badge&logo=npm&logoColor=white&color=cb3837" alt="npm version"/></a>
|
|
16
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-blue.svg?style=for-the-badge" alt="License: MIT"/></a>
|
|
17
|
+
<a href="https://nodejs.org/"><img src="https://img.shields.io/node/v/hispano-lang?style=for-the-badge&logo=node.js&logoColor=white&color=339933" alt="Node.js Version"/></a>
|
|
18
|
+
<a href="https://www.npmjs.com/package/hispano-lang"><img src="https://img.shields.io/npm/dm/hispano-lang?style=for-the-badge&color=blue" alt="Downloads"/></a>
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
<p align="center">
|
|
22
|
+
<a href="#inicio-rápido">Inicio Rápido</a> •
|
|
23
|
+
<a href="#instalación">Instalación</a> •
|
|
24
|
+
<a href="#referencia-del-lenguaje">Documentación</a> •
|
|
25
|
+
<a href="#ejemplos">Ejemplos</a> •
|
|
26
|
+
<a href="#contribuir">Contribuir</a>
|
|
27
|
+
</p>
|
|
2
28
|
|
|
3
|
-
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Tabla de Contenidos
|
|
32
|
+
|
|
33
|
+
- [Acerca de HispanoLang](#acerca-de-hispanolang)
|
|
34
|
+
- [Inicio Rápido](#inicio-rápido)
|
|
35
|
+
- [Instalación](#instalación)
|
|
36
|
+
- [Referencia del Lenguaje](#referencia-del-lenguaje)
|
|
37
|
+
- [Variables y Constantes](#variables-y-constantes)
|
|
38
|
+
- [Tipos de Datos](#tipos-de-datos)
|
|
39
|
+
- [Operadores](#operadores)
|
|
40
|
+
- [Estructuras de Control](#estructuras-de-control)
|
|
41
|
+
- [Funciones](#funciones)
|
|
42
|
+
- [Programación Orientada a Objetos](#programación-orientada-a-objetos)
|
|
43
|
+
- [Colecciones](#colecciones)
|
|
44
|
+
- [Manejo de Errores](#manejo-de-errores)
|
|
45
|
+
- [Ejemplos](#ejemplos)
|
|
46
|
+
- [API de Node.js](#api-de-nodejs)
|
|
47
|
+
- [Arquitectura](#arquitectura)
|
|
48
|
+
- [Contribuir](#contribuir)
|
|
49
|
+
- [Licencia](#licencia)
|
|
50
|
+
|
|
51
|
+
---
|
|
4
52
|
|
|
5
|
-
|
|
53
|
+
## Acerca de HispanoLang
|
|
6
54
|
|
|
7
|
-
|
|
8
|
-
[](https://opensource.org/licenses/MIT)
|
|
9
|
-
[](https://nodejs.org/)
|
|
10
|
-
[](https://www.npmjs.com/package/hispano-lang)
|
|
55
|
+
HispanoLang es un lenguaje de programación interpretado con sintaxis completamente en español. Fue diseñado con un objetivo claro: **democratizar el acceso a la programación** para los más de 500 millones de hispanohablantes en el mundo.
|
|
11
56
|
|
|
12
|
-
|
|
57
|
+
### ¿Por qué HispanoLang?
|
|
13
58
|
|
|
14
|
-
|
|
59
|
+
La mayoría de los lenguajes de programación utilizan palabras clave en inglés, creando una barrera adicional para quienes están aprendiendo a programar. HispanoLang elimina esta barrera, permitiendo que los estudiantes se concentren en los **conceptos fundamentales** de la programación sin tener que lidiar simultáneamente con un idioma extranjero.
|
|
60
|
+
|
|
61
|
+
### Características
|
|
62
|
+
|
|
63
|
+
| Característica | Descripción |
|
|
64
|
+
| ------------------------------ | ---------------------------------------------------------------------- |
|
|
65
|
+
| **Sintaxis en Español** | Palabras clave intuitivas como `variable`, `funcion`, `si`, `mientras` |
|
|
66
|
+
| **Tipado Dinámico** | Sistema de tipos flexible con conversiones automáticas |
|
|
67
|
+
| **POO Completa** | Clases, herencia, constructores y métodos |
|
|
68
|
+
| **Funciones de Primera Clase** | Funciones como valores, closures y callbacks |
|
|
69
|
+
| **Colecciones Ricas** | Arrays y objetos con métodos funcionales integrados |
|
|
70
|
+
| **REPL Interactivo** | Experimenta con código en tiempo real |
|
|
71
|
+
| **Integración Node.js** | Usa HispanoLang como módulo en proyectos JavaScript |
|
|
72
|
+
| **TypeScript Ready** | Definiciones de tipos incluidas |
|
|
73
|
+
|
|
74
|
+
---
|
|
15
75
|
|
|
16
|
-
##
|
|
76
|
+
## Inicio Rápido
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# Instalar globalmente
|
|
80
|
+
npm install -g hispano-lang
|
|
81
|
+
|
|
82
|
+
# Iniciar el REPL interactivo
|
|
83
|
+
hispano
|
|
84
|
+
|
|
85
|
+
# O ejecutar un archivo
|
|
86
|
+
hispano mi_programa.hl
|
|
87
|
+
```
|
|
17
88
|
|
|
18
|
-
|
|
89
|
+
Tu primer programa en HispanoLang:
|
|
19
90
|
|
|
20
|
-
|
|
91
|
+
```
|
|
92
|
+
variable mensaje = "¡Hola, mundo!"
|
|
93
|
+
mostrar mensaje
|
|
94
|
+
```
|
|
21
95
|
|
|
22
|
-
|
|
23
|
-
- ⚡ **Intérprete completo** - Implementado en JavaScript/Node.js
|
|
24
|
-
- 🎓 **Minimalista** - Pensado para aprender lógica sin distracciones
|
|
25
|
-
- 📚 **Educativo** - Enfoque en conceptos fundamentales
|
|
26
|
-
- 🔧 **CLI Tool** - Interfaz de línea de comandos intuitiva
|
|
27
|
-
- 🧪 **Suite de tests** - 170+ tests para garantizar calidad
|
|
28
|
-
- 📦 **NPM Package** - Fácil instalación y distribución
|
|
29
|
-
- 🔄 **REPL Interactivo** - Modo interactivo para experimentar
|
|
30
|
-
- 📝 **TypeScript Support** - Definiciones de tipos incluidas
|
|
31
|
-
- 🌍 **Open Source** - Libre para usar, modificar y contribuir
|
|
96
|
+
---
|
|
32
97
|
|
|
33
|
-
##
|
|
98
|
+
## Instalación
|
|
34
99
|
|
|
35
|
-
###
|
|
100
|
+
### Requisitos
|
|
36
101
|
|
|
37
|
-
-
|
|
38
|
-
-
|
|
102
|
+
- Node.js 20.0.0 o superior
|
|
103
|
+
- npm o yarn
|
|
39
104
|
|
|
40
105
|
### Instalación Global (Recomendada)
|
|
41
106
|
|
|
@@ -43,347 +108,717 @@ La mayoría de los lenguajes de programación utilizan palabras clave en inglés
|
|
|
43
108
|
npm install -g hispano-lang
|
|
44
109
|
```
|
|
45
110
|
|
|
46
|
-
### Instalación
|
|
111
|
+
### Instalación como Dependencia
|
|
47
112
|
|
|
48
113
|
```bash
|
|
49
114
|
npm install hispano-lang
|
|
50
115
|
```
|
|
51
116
|
|
|
52
|
-
###
|
|
117
|
+
### Desde el Código Fuente
|
|
53
118
|
|
|
54
119
|
```bash
|
|
55
120
|
git clone https://github.com/nicvazquezdev/hispano-lang.git
|
|
56
121
|
cd hispano-lang
|
|
57
122
|
npm install
|
|
58
123
|
npm run build
|
|
124
|
+
npm link
|
|
59
125
|
```
|
|
60
126
|
|
|
61
|
-
|
|
127
|
+
### Verificar Instalación
|
|
62
128
|
|
|
63
|
-
|
|
129
|
+
```bash
|
|
130
|
+
hispano --version
|
|
131
|
+
```
|
|
64
132
|
|
|
65
|
-
|
|
133
|
+
---
|
|
66
134
|
|
|
67
|
-
|
|
68
|
-
# Modo interactivo (REPL)
|
|
69
|
-
hispano
|
|
135
|
+
## Referencia del Lenguaje
|
|
70
136
|
|
|
71
|
-
|
|
72
|
-
hispano script.hl
|
|
137
|
+
### Variables y Constantes
|
|
73
138
|
|
|
74
|
-
|
|
75
|
-
hispano -e "mostrar 'Hola mundo'"
|
|
139
|
+
#### Variables
|
|
76
140
|
|
|
77
|
-
|
|
78
|
-
hispano --help
|
|
141
|
+
Las variables se declaran con la palabra clave `variable` y pueden ser reasignadas:
|
|
79
142
|
|
|
80
|
-
# Ejecutar tests
|
|
81
|
-
hispano --test
|
|
82
143
|
```
|
|
144
|
+
variable nombre = "Ana"
|
|
145
|
+
variable edad = 25
|
|
146
|
+
variable activo = verdadero
|
|
83
147
|
|
|
84
|
-
|
|
148
|
+
edad = 26 // Reasignación permitida
|
|
149
|
+
```
|
|
85
150
|
|
|
86
|
-
|
|
87
|
-
const { interpret, run, getVariables } = require('hispano-lang');
|
|
151
|
+
#### Constantes
|
|
88
152
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
153
|
+
Las constantes se declaran con `constante` y no pueden ser reasignadas:
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
constante PI = 3.14159
|
|
157
|
+
constante MAX_INTENTOS = 3
|
|
158
|
+
constante VERSION = "2.0.0"
|
|
94
159
|
|
|
95
|
-
|
|
160
|
+
PI = 3.14 // Error: No se puede reasignar la constante
|
|
161
|
+
```
|
|
96
162
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
### Tipos de Datos
|
|
166
|
+
|
|
167
|
+
| Tipo | Ejemplo | Descripción |
|
|
168
|
+
| ---------- | -------------------- | ------------------------------ |
|
|
169
|
+
| Número | `42`, `3.14`, `-10` | Enteros y decimales |
|
|
170
|
+
| Texto | `"Hola"`, `'Mundo'` | Cadenas de caracteres |
|
|
171
|
+
| Booleano | `verdadero`, `falso` | Valores lógicos |
|
|
172
|
+
| Arreglo | `[1, 2, 3]` | Colección ordenada |
|
|
173
|
+
| Objeto | `{ clave: valor }` | Colección de pares clave-valor |
|
|
174
|
+
| Nulo | `nulo` | Ausencia intencional de valor |
|
|
175
|
+
| Indefinido | `indefinido` | Variable sin valor asignado |
|
|
176
|
+
| Función | `funcion() {}` | Bloque de código reutilizable |
|
|
177
|
+
| Clase | `clase {}` | Plantilla para crear objetos |
|
|
178
|
+
|
|
179
|
+
#### Conversión de Tipos
|
|
102
180
|
|
|
103
|
-
console.log(outputs); // ['20']
|
|
104
181
|
```
|
|
182
|
+
entero("42") // 42
|
|
183
|
+
entero(3.7) // 3
|
|
105
184
|
|
|
106
|
-
|
|
185
|
+
decimal("3.14") // 3.14
|
|
107
186
|
|
|
108
|
-
|
|
109
|
-
|
|
187
|
+
texto(123) // "123"
|
|
188
|
+
texto(verdadero) // "verdadero"
|
|
110
189
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
190
|
+
booleano(1) // verdadero
|
|
191
|
+
booleano("") // falso
|
|
192
|
+
|
|
193
|
+
tipo(42) // "numero"
|
|
194
|
+
tipo("hola") // "texto"
|
|
195
|
+
tipo([1, 2]) // "arreglo"
|
|
117
196
|
```
|
|
118
197
|
|
|
119
|
-
|
|
198
|
+
---
|
|
120
199
|
|
|
121
|
-
###
|
|
200
|
+
### Operadores
|
|
122
201
|
|
|
123
|
-
|
|
124
|
-
// Saludo personalizado
|
|
125
|
-
variable nombre = "María"
|
|
126
|
-
mostrar "¡Hola " + nombre + "!"
|
|
202
|
+
#### Aritméticos
|
|
127
203
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
204
|
+
| Operador | Descripción | Ejemplo |
|
|
205
|
+
| -------- | -------------- | -------------- |
|
|
206
|
+
| `+` | Suma | `5 + 3` → `8` |
|
|
207
|
+
| `-` | Resta | `5 - 3` → `2` |
|
|
208
|
+
| `*` | Multiplicación | `5 * 3` → `15` |
|
|
209
|
+
| `/` | División | `6 / 2` → `3` |
|
|
210
|
+
| `%` | Módulo | `7 % 3` → `1` |
|
|
133
211
|
|
|
134
|
-
|
|
135
|
-
si suma > 10 {
|
|
136
|
-
mostrar "¡Es un número grande!"
|
|
137
|
-
} sino {
|
|
138
|
-
mostrar "Es un número pequeño"
|
|
139
|
-
}
|
|
140
|
-
```
|
|
212
|
+
#### Comparación
|
|
141
213
|
|
|
142
|
-
|
|
214
|
+
| Operador | Descripción | Ejemplo |
|
|
215
|
+
| -------- | ------------- | ---------------------- |
|
|
216
|
+
| `==` | Igual a | `5 == 5` → `verdadero` |
|
|
217
|
+
| `!=` | Diferente de | `5 != 3` → `verdadero` |
|
|
218
|
+
| `<` | Menor que | `3 < 5` → `verdadero` |
|
|
219
|
+
| `>` | Mayor que | `5 > 3` → `verdadero` |
|
|
220
|
+
| `<=` | Menor o igual | `3 <= 3` → `verdadero` |
|
|
221
|
+
| `>=` | Mayor o igual | `5 >= 5` → `verdadero` |
|
|
143
222
|
|
|
144
|
-
|
|
145
|
-
variable nombre = "Juan"
|
|
146
|
-
variable edad = 25
|
|
147
|
-
variable activo = verdadero
|
|
148
|
-
variable salario = 50000.50
|
|
149
|
-
```
|
|
223
|
+
#### Lógicos
|
|
150
224
|
|
|
151
|
-
|
|
225
|
+
| Operador | Descripción | Ejemplo |
|
|
226
|
+
| -------- | ----------- | --------------------------------- |
|
|
227
|
+
| `y` | AND lógico | `verdadero y falso` → `falso` |
|
|
228
|
+
| `o` | OR lógico | `verdadero o falso` → `verdadero` |
|
|
229
|
+
| `!` | NOT lógico | `!verdadero` → `falso` |
|
|
152
230
|
|
|
153
|
-
|
|
154
|
-
// Entrada básica
|
|
155
|
-
leer nombre
|
|
156
|
-
mostrar "Hola " + nombre
|
|
231
|
+
#### Asignación Compuesta
|
|
157
232
|
|
|
158
|
-
// Entrada con mensaje
|
|
159
|
-
leer edad "¿Cuál es tu edad?"
|
|
160
|
-
mostrar "Tienes " + edad + " años"
|
|
161
233
|
```
|
|
234
|
+
variable x = 10
|
|
235
|
+
x += 5 // x = 15
|
|
236
|
+
x -= 3 // x = 12
|
|
237
|
+
x *= 2 // x = 24
|
|
238
|
+
x /= 4 // x = 6
|
|
239
|
+
x %= 4 // x = 2
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
---
|
|
162
243
|
|
|
163
|
-
###
|
|
244
|
+
### Estructuras de Control
|
|
164
245
|
|
|
165
|
-
|
|
246
|
+
#### Condicional Si/Sino
|
|
247
|
+
|
|
248
|
+
```
|
|
166
249
|
si edad >= 18 {
|
|
167
|
-
|
|
250
|
+
mostrar "Mayor de edad"
|
|
168
251
|
} sino {
|
|
169
|
-
|
|
252
|
+
mostrar "Menor de edad"
|
|
170
253
|
}
|
|
171
254
|
```
|
|
172
255
|
|
|
173
|
-
|
|
256
|
+
#### Elegir/Caso (Switch)
|
|
174
257
|
|
|
175
|
-
```
|
|
176
|
-
|
|
258
|
+
```
|
|
259
|
+
elegir opcion {
|
|
260
|
+
caso 1: mostrar "Opción uno"
|
|
261
|
+
caso 2: mostrar "Opción dos"
|
|
262
|
+
caso 3: {
|
|
263
|
+
mostrar "Opción tres"
|
|
264
|
+
mostrar "Con múltiples líneas"
|
|
265
|
+
}
|
|
266
|
+
pordefecto: mostrar "Opción no válida"
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
#### Bucle Mientras
|
|
271
|
+
|
|
272
|
+
```
|
|
177
273
|
variable i = 0
|
|
178
274
|
mientras i < 5 {
|
|
179
|
-
|
|
180
|
-
|
|
275
|
+
mostrar i
|
|
276
|
+
i = i + 1
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
#### Bucle Para
|
|
281
|
+
|
|
282
|
+
```
|
|
283
|
+
para (variable i = 0; i < 5; i = i + 1) {
|
|
284
|
+
mostrar i
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
#### Bucle Hacer/Mientras
|
|
289
|
+
|
|
290
|
+
```
|
|
291
|
+
variable x = 0
|
|
292
|
+
hacer {
|
|
293
|
+
mostrar x
|
|
294
|
+
x = x + 1
|
|
295
|
+
} mientras x < 3
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
#### Bucle Para Cada
|
|
299
|
+
|
|
300
|
+
```
|
|
301
|
+
variable frutas = ["manzana", "banana", "naranja"]
|
|
302
|
+
para cada fruta en frutas {
|
|
303
|
+
mostrar fruta
|
|
181
304
|
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
#### Control de Flujo
|
|
182
308
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
309
|
+
```
|
|
310
|
+
mientras verdadero {
|
|
311
|
+
si condicion {
|
|
312
|
+
romper // Sale del bucle
|
|
313
|
+
}
|
|
314
|
+
si otraCondicion {
|
|
315
|
+
continuar // Salta a la siguiente iteración
|
|
316
|
+
}
|
|
186
317
|
}
|
|
187
318
|
```
|
|
188
319
|
|
|
320
|
+
---
|
|
321
|
+
|
|
189
322
|
### Funciones
|
|
190
323
|
|
|
191
|
-
|
|
324
|
+
#### Declaración y Llamada
|
|
325
|
+
|
|
326
|
+
```
|
|
192
327
|
funcion saludar(nombre) {
|
|
193
|
-
|
|
328
|
+
retornar "Hola, " + nombre
|
|
194
329
|
}
|
|
195
330
|
|
|
196
|
-
mostrar saludar("
|
|
331
|
+
mostrar saludar("María") // "Hola, María"
|
|
197
332
|
```
|
|
198
333
|
|
|
199
|
-
|
|
334
|
+
#### Funciones Anónimas
|
|
200
335
|
|
|
201
|
-
```
|
|
202
|
-
variable
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
mostrar frutas.ultimo() // naranja
|
|
336
|
+
```
|
|
337
|
+
variable duplicar = funcion(x) {
|
|
338
|
+
retornar x * 2
|
|
339
|
+
}
|
|
206
340
|
|
|
207
|
-
//
|
|
208
|
-
frutas.agregar("uva") // push
|
|
209
|
-
frutas.remover() // pop
|
|
210
|
-
frutas.contiene("banana") // includes
|
|
341
|
+
mostrar duplicar(5) // 10
|
|
211
342
|
```
|
|
212
343
|
|
|
213
|
-
|
|
344
|
+
#### Arrow Functions
|
|
214
345
|
|
|
215
|
-
|
|
346
|
+
Sintaxis concisa para funciones anónimas:
|
|
347
|
+
|
|
348
|
+
```
|
|
349
|
+
// Un parámetro (sin paréntesis)
|
|
350
|
+
variable doble = x => x * 2
|
|
351
|
+
|
|
352
|
+
// Múltiples parámetros
|
|
353
|
+
variable suma = (a, b) => a + b
|
|
354
|
+
|
|
355
|
+
// Sin parámetros
|
|
356
|
+
variable saludar = () => "Hola mundo"
|
|
357
|
+
|
|
358
|
+
// Con bloque de código
|
|
359
|
+
variable factorial = n => {
|
|
360
|
+
si (n <= 1) { retornar 1 }
|
|
361
|
+
retornar n * factorial(n - 1)
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
mostrar doble(5) // 10
|
|
365
|
+
mostrar suma(3, 4) // 7
|
|
366
|
+
mostrar factorial(5) // 120
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
Arrow functions son ideales para callbacks:
|
|
370
|
+
|
|
371
|
+
```
|
|
372
|
+
variable numeros = [1, 2, 3, 4, 5]
|
|
373
|
+
|
|
374
|
+
numeros.mapear(x => x * 2) // [2, 4, 6, 8, 10]
|
|
375
|
+
numeros.filtrar(x => x > 2) // [3, 4, 5]
|
|
376
|
+
numeros.reducir((a, b) => a + b, 0) // 15
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
#### Funciones como Parámetros
|
|
380
|
+
|
|
381
|
+
```
|
|
382
|
+
funcion aplicar(valor, operacion) {
|
|
383
|
+
retornar operacion(valor)
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
variable resultado = aplicar(5, funcion(x) { retornar x * x })
|
|
387
|
+
mostrar resultado // 25
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
#### Funciones Matemáticas Integradas
|
|
391
|
+
|
|
392
|
+
```
|
|
393
|
+
raiz(16) // 4
|
|
394
|
+
potencia(2, 8) // 256
|
|
395
|
+
absoluto(-5) // 5
|
|
396
|
+
redondear(3.7) // 4
|
|
397
|
+
piso(3.7) // 3
|
|
398
|
+
techo(3.2) // 4
|
|
399
|
+
seno(0) // 0
|
|
400
|
+
coseno(0) // 1
|
|
401
|
+
tangente(0) // 0
|
|
402
|
+
aleatorio() // Número entre 0 y 1
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
### Programación Orientada a Objetos
|
|
408
|
+
|
|
409
|
+
#### Definición de Clases
|
|
410
|
+
|
|
411
|
+
```
|
|
412
|
+
clase Persona {
|
|
413
|
+
constructor(nombre, edad) {
|
|
414
|
+
este.nombre = nombre
|
|
415
|
+
este.edad = edad
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
saludar() {
|
|
419
|
+
retornar "Hola, soy " + este.nombre
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
cumplirAnios() {
|
|
423
|
+
este.edad = este.edad + 1
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
#### Instanciación
|
|
429
|
+
|
|
430
|
+
```
|
|
431
|
+
variable persona = nuevo Persona("Carlos", 30)
|
|
432
|
+
mostrar persona.nombre // "Carlos"
|
|
433
|
+
mostrar persona.saludar() // "Hola, soy Carlos"
|
|
434
|
+
|
|
435
|
+
persona.cumplirAnios()
|
|
436
|
+
mostrar persona.edad // 31
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
#### Herencia
|
|
440
|
+
|
|
441
|
+
```
|
|
442
|
+
clase Empleado extiende Persona {
|
|
443
|
+
constructor(nombre, edad, cargo) {
|
|
444
|
+
super(nombre, edad)
|
|
445
|
+
este.cargo = cargo
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
presentarse() {
|
|
449
|
+
retornar este.saludar() + " y trabajo como " + este.cargo
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
variable emp = nuevo Empleado("Ana", 28, "Ingeniera")
|
|
454
|
+
mostrar emp.presentarse() // "Hola, soy Ana y trabajo como Ingeniera"
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
#### Verificación de Tipo
|
|
458
|
+
|
|
459
|
+
```
|
|
460
|
+
variable p = nuevo Persona("Luis", 25)
|
|
461
|
+
mostrar tipo(p) // "Persona"
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
466
|
+
### Colecciones
|
|
467
|
+
|
|
468
|
+
#### Arreglos
|
|
469
|
+
|
|
470
|
+
```
|
|
471
|
+
variable numeros = [1, 2, 3, 4, 5]
|
|
472
|
+
|
|
473
|
+
// Acceso y modificación
|
|
474
|
+
mostrar numeros[0] // 1
|
|
475
|
+
numeros[0] = 10
|
|
476
|
+
|
|
477
|
+
// Propiedades y métodos básicos
|
|
478
|
+
numeros.longitud() // 5
|
|
479
|
+
numeros.primero() // 10
|
|
480
|
+
numeros.ultimo() // 5
|
|
481
|
+
numeros.agregar(6) // Añade al final
|
|
482
|
+
numeros.remover() // Remueve del final
|
|
483
|
+
numeros.contiene(3) // verdadero
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
#### Métodos Funcionales
|
|
487
|
+
|
|
488
|
+
```
|
|
489
|
+
variable nums = [1, 2, 3, 4, 5]
|
|
490
|
+
|
|
491
|
+
// Transformación
|
|
492
|
+
nums.mapear(funcion(x) { retornar x * 2 })
|
|
493
|
+
// [2, 4, 6, 8, 10]
|
|
494
|
+
|
|
495
|
+
// Filtrado
|
|
496
|
+
nums.filtrar(funcion(x) { retornar x > 2 })
|
|
497
|
+
// [3, 4, 5]
|
|
498
|
+
|
|
499
|
+
// Reducción
|
|
500
|
+
nums.reducir(funcion(acc, x) { retornar acc + x }, 0)
|
|
501
|
+
// 15
|
|
502
|
+
|
|
503
|
+
// Búsqueda
|
|
504
|
+
nums.buscar(funcion(x) { retornar x > 3 })
|
|
505
|
+
// 4
|
|
506
|
+
|
|
507
|
+
// Verificación
|
|
508
|
+
nums.algunos(funcion(x) { retornar x > 4 }) // verdadero
|
|
509
|
+
nums.todos(funcion(x) { retornar x > 0 }) // verdadero
|
|
510
|
+
|
|
511
|
+
// Ordenamiento
|
|
512
|
+
nums.ordenar() // [1, 2, 3, 4, 5]
|
|
513
|
+
nums.invertir() // [5, 4, 3, 2, 1]
|
|
514
|
+
|
|
515
|
+
// Manipulación
|
|
516
|
+
nums.cortar(1, 3) // [2, 3]
|
|
517
|
+
nums.insertar(2, 99) // Inserta 99 en posición 2
|
|
518
|
+
nums.unir(", ") // "1, 2, 3, 4, 5"
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
#### Iteración
|
|
522
|
+
|
|
523
|
+
```
|
|
524
|
+
variable colores = ["rojo", "verde", "azul"]
|
|
525
|
+
colores.recorrer(funcion() {
|
|
526
|
+
mostrar "Color: " + elemento + " en índice " + indice
|
|
527
|
+
})
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
#### Objetos
|
|
531
|
+
|
|
532
|
+
```
|
|
216
533
|
variable persona = {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
534
|
+
nombre: "Elena",
|
|
535
|
+
edad: 32,
|
|
536
|
+
ciudad: "Madrid"
|
|
220
537
|
}
|
|
221
538
|
|
|
222
|
-
mostrar persona.nombre //
|
|
223
|
-
persona.edad =
|
|
539
|
+
mostrar persona.nombre // "Elena"
|
|
540
|
+
persona.edad = 33 // Modificar
|
|
541
|
+
persona.profesion = "Dev" // Añadir propiedad
|
|
224
542
|
```
|
|
225
543
|
|
|
226
|
-
|
|
544
|
+
#### Cadenas de Texto
|
|
227
545
|
|
|
228
|
-
```javascript
|
|
229
|
-
variable texto = "hola mundo"
|
|
230
|
-
mostrar texto.longitud() // 10
|
|
231
|
-
mostrar texto.mayusculas() // HOLA MUNDO
|
|
232
|
-
mostrar texto.minusculas() // hola mundo
|
|
233
546
|
```
|
|
547
|
+
variable texto = "Hola Mundo"
|
|
234
548
|
|
|
235
|
-
|
|
549
|
+
// Propiedades
|
|
550
|
+
texto.longitud() // 10
|
|
236
551
|
|
|
237
|
-
|
|
552
|
+
// Transformación
|
|
553
|
+
texto.mayusculas() // "HOLA MUNDO"
|
|
554
|
+
texto.minusculas() // "hola mundo"
|
|
555
|
+
texto.recortar() // Elimina espacios extremos
|
|
556
|
+
texto.invertir() // "odnuM aloH"
|
|
557
|
+
|
|
558
|
+
// Búsqueda
|
|
559
|
+
texto.incluye("Mundo") // verdadero
|
|
560
|
+
texto.empiezaCon("Hola") // verdadero
|
|
561
|
+
texto.terminaCon("Mundo") // verdadero
|
|
562
|
+
|
|
563
|
+
// Extracción
|
|
564
|
+
texto.caracter(0) // "H"
|
|
565
|
+
texto.subcadena(0, 4) // "Hola"
|
|
566
|
+
|
|
567
|
+
// Manipulación
|
|
568
|
+
texto.dividir(" ") // ["Hola", "Mundo"]
|
|
569
|
+
texto.reemplazar("Mundo", "Amigo") // "Hola Amigo"
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
#### Interpolación de Cadenas
|
|
573
|
+
|
|
574
|
+
```
|
|
575
|
+
variable nombre = "María"
|
|
576
|
+
variable edad = 25
|
|
577
|
+
|
|
578
|
+
mostrar `Hola ${nombre}, tienes ${edad} años`
|
|
579
|
+
// "Hola María, tienes 25 años"
|
|
580
|
+
|
|
581
|
+
mostrar `El doble de tu edad es ${edad * 2}`
|
|
582
|
+
// "El doble de tu edad es 50"
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
#### Métodos Numéricos
|
|
586
|
+
|
|
587
|
+
```
|
|
588
|
+
variable n = 42
|
|
589
|
+
|
|
590
|
+
n.esPar() // verdadero
|
|
591
|
+
n.esImpar() // falso
|
|
592
|
+
n.esPositivo() // verdadero
|
|
593
|
+
n.esNegativo() // falso
|
|
594
|
+
n.aTexto() // "42"
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
---
|
|
598
|
+
|
|
599
|
+
### Manejo de Errores
|
|
600
|
+
|
|
601
|
+
```
|
|
238
602
|
intentar {
|
|
239
|
-
|
|
603
|
+
variable resultado = operacionRiesgosa()
|
|
604
|
+
mostrar resultado
|
|
240
605
|
} capturar (error) {
|
|
241
|
-
|
|
606
|
+
mostrar "Ocurrió un error: " + error
|
|
242
607
|
}
|
|
243
608
|
```
|
|
244
609
|
|
|
245
|
-
|
|
610
|
+
---
|
|
246
611
|
|
|
247
|
-
|
|
248
|
-
variable valorNulo = nulo
|
|
249
|
-
variable valorIndefinido = indefinido
|
|
250
|
-
```
|
|
612
|
+
## Ejemplos
|
|
251
613
|
|
|
252
|
-
|
|
614
|
+
### Calculadora Simple
|
|
253
615
|
|
|
254
|
-
|
|
616
|
+
```
|
|
617
|
+
funcion calculadora(a, b, operacion) {
|
|
618
|
+
elegir operacion {
|
|
619
|
+
caso "+": retornar a + b
|
|
620
|
+
caso "-": retornar a - b
|
|
621
|
+
caso "*": retornar a * b
|
|
622
|
+
caso "/": {
|
|
623
|
+
si b == 0 {
|
|
624
|
+
retornar "Error: División por cero"
|
|
625
|
+
}
|
|
626
|
+
retornar a / b
|
|
627
|
+
}
|
|
628
|
+
pordefecto: retornar "Operación no válida"
|
|
629
|
+
}
|
|
630
|
+
}
|
|
255
631
|
|
|
256
|
-
|
|
257
|
-
|
|
632
|
+
mostrar calculadora(10, 5, "+") // 15
|
|
633
|
+
mostrar calculadora(10, 5, "*") // 50
|
|
258
634
|
```
|
|
259
635
|
|
|
260
|
-
|
|
636
|
+
### Fibonacci
|
|
637
|
+
|
|
638
|
+
```
|
|
639
|
+
funcion fibonacci(n) {
|
|
640
|
+
si n <= 1 {
|
|
641
|
+
retornar n
|
|
642
|
+
}
|
|
643
|
+
retornar fibonacci(n - 1) + fibonacci(n - 2)
|
|
644
|
+
}
|
|
261
645
|
|
|
646
|
+
para (variable i = 0; i < 10; i = i + 1) {
|
|
647
|
+
mostrar fibonacci(i)
|
|
648
|
+
}
|
|
262
649
|
```
|
|
263
|
-
src/
|
|
264
|
-
├── tokenizer.js # Análisis léxico
|
|
265
|
-
├── parser.js # Análisis sintáctico
|
|
266
|
-
├── evaluator.js # Evaluación de expresiones
|
|
267
|
-
└── interpreter.js # Orquestador principal
|
|
268
650
|
|
|
269
|
-
|
|
270
|
-
└── hispano.js # CLI tool
|
|
651
|
+
### Sistema de Gestión
|
|
271
652
|
|
|
272
|
-
test/
|
|
273
|
-
└── test.js # Suite completa de tests (170+ casos)
|
|
274
653
|
```
|
|
654
|
+
clase Producto {
|
|
655
|
+
constructor(nombre, precio) {
|
|
656
|
+
este.nombre = nombre
|
|
657
|
+
este.precio = precio
|
|
658
|
+
}
|
|
659
|
+
}
|
|
275
660
|
|
|
276
|
-
|
|
661
|
+
clase Carrito {
|
|
662
|
+
constructor() {
|
|
663
|
+
este.productos = []
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
agregar(producto) {
|
|
667
|
+
este.productos.agregar(producto)
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
total() {
|
|
671
|
+
retornar este.productos.reducir(
|
|
672
|
+
funcion(acc, p) { retornar acc + p.precio },
|
|
673
|
+
0
|
|
674
|
+
)
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
mostrarResumen() {
|
|
678
|
+
mostrar "=== Carrito de Compras ==="
|
|
679
|
+
para cada producto en este.productos {
|
|
680
|
+
mostrar `${producto.nombre}: $${producto.precio}`
|
|
681
|
+
}
|
|
682
|
+
mostrar `Total: $${este.total()}`
|
|
683
|
+
}
|
|
684
|
+
}
|
|
277
685
|
|
|
278
|
-
|
|
686
|
+
variable carrito = nuevo Carrito()
|
|
687
|
+
carrito.agregar(nuevo Producto("Laptop", 999))
|
|
688
|
+
carrito.agregar(nuevo Producto("Mouse", 29))
|
|
689
|
+
carrito.agregar(nuevo Producto("Teclado", 79))
|
|
690
|
+
carrito.mostrarResumen()
|
|
691
|
+
```
|
|
279
692
|
|
|
280
|
-
|
|
281
|
-
# Clonar el repositorio
|
|
282
|
-
git clone https://github.com/nicvazquezdev/hispano-lang.git
|
|
283
|
-
cd hispano-lang
|
|
693
|
+
---
|
|
284
694
|
|
|
285
|
-
|
|
286
|
-
npm install
|
|
695
|
+
## API de Node.js
|
|
287
696
|
|
|
288
|
-
|
|
289
|
-
npm run dev
|
|
697
|
+
### Uso como Módulo
|
|
290
698
|
|
|
291
|
-
|
|
292
|
-
|
|
699
|
+
```javascript
|
|
700
|
+
const { interpret, run } = require("hispano-lang");
|
|
293
701
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
702
|
+
// Interpretar código y obtener resultado completo
|
|
703
|
+
const result = interpret(`
|
|
704
|
+
variable x = 10
|
|
705
|
+
mostrar x * 2
|
|
706
|
+
`);
|
|
297
707
|
|
|
298
|
-
|
|
299
|
-
|
|
708
|
+
console.log(result.success); // true
|
|
709
|
+
console.log(result.output); // ['20']
|
|
710
|
+
console.log(result.error); // null
|
|
711
|
+
|
|
712
|
+
// Ejecutar y obtener solo la salida
|
|
713
|
+
const output = run(`mostrar "Hola desde Node.js"`);
|
|
714
|
+
console.log(output); // ['Hola desde Node.js']
|
|
300
715
|
```
|
|
301
716
|
|
|
302
|
-
###
|
|
717
|
+
### TypeScript
|
|
303
718
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
- `npm run dev` - Modo desarrollo con nodemon
|
|
307
|
-
- `npm run lint` - Verificar código con ESLint
|
|
308
|
-
- `npm run format` - Formatear código con Prettier
|
|
309
|
-
- `npm run build` - Construir para producción
|
|
310
|
-
- `npm run demo` - Ejecutar demo
|
|
719
|
+
```typescript
|
|
720
|
+
import { interpret, InterpretationResult } from "hispano-lang";
|
|
311
721
|
|
|
312
|
-
|
|
722
|
+
const result: InterpretationResult = interpret(`
|
|
723
|
+
variable mensaje = "TypeScript + HispanoLang"
|
|
724
|
+
mostrar mensaje
|
|
725
|
+
`);
|
|
726
|
+
```
|
|
313
727
|
|
|
314
|
-
|
|
728
|
+
---
|
|
315
729
|
|
|
316
|
-
|
|
730
|
+
## Arquitectura
|
|
317
731
|
|
|
318
|
-
|
|
319
|
-
2. **Crea** una rama para tu feature (`git checkout -b feature/AmazingFeature`)
|
|
320
|
-
3. **Commit** tus cambios (`git commit -m 'Add some AmazingFeature'`)
|
|
321
|
-
4. **Push** a la rama (`git push origin feature/AmazingFeature`)
|
|
322
|
-
5. **Abre** un Pull Request
|
|
732
|
+
HispanoLang utiliza una arquitectura de intérprete clásica con tres fases:
|
|
323
733
|
|
|
324
|
-
|
|
734
|
+
```
|
|
735
|
+
┌─────────────┐ ┌────────────┐ ┌─────────────┐
|
|
736
|
+
│ Tokenizer │ ──▶ │ Parser │ ──▶ │ Evaluator │
|
|
737
|
+
│ (Léxico) │ │ (Sintaxis) │ │ (Ejecución) │
|
|
738
|
+
└─────────────┘ └────────────┘ └─────────────┘
|
|
739
|
+
│ │ │
|
|
740
|
+
▼ ▼ ▼
|
|
741
|
+
Tokens AST Resultado
|
|
742
|
+
```
|
|
325
743
|
|
|
326
|
-
|
|
327
|
-
- ✅ Añade tests para nuevas funcionalidades
|
|
328
|
-
- ✅ Actualiza la documentación si es necesario
|
|
329
|
-
- ✅ Asegúrate de que todos los tests pasen
|
|
330
|
-
- ✅ Usa `npm run lint` y `npm run format` antes de commitear
|
|
744
|
+
### Estructura del Proyecto
|
|
331
745
|
|
|
332
|
-
|
|
746
|
+
```
|
|
747
|
+
hispano-lang/
|
|
748
|
+
├── src/
|
|
749
|
+
│ ├── tokenizer.js # Análisis léxico
|
|
750
|
+
│ ├── parser.js # Análisis sintáctico → AST
|
|
751
|
+
│ ├── evaluator.js # Evaluación del AST
|
|
752
|
+
│ └── interpreter.js # Orquestador principal
|
|
753
|
+
├── bin/
|
|
754
|
+
│ └── hispano.js # CLI
|
|
755
|
+
├── test/
|
|
756
|
+
│ └── test.js # Suite de tests (310+)
|
|
757
|
+
└── dist/ # Build de producción
|
|
758
|
+
```
|
|
333
759
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
- 🧪 **Tests** - Añade casos de prueba
|
|
338
|
-
- 🌍 **Traducciones** - Ayuda con documentación en otros idiomas
|
|
339
|
-
- 🎨 **UI/UX** - Mejora la experiencia del CLI
|
|
760
|
+
---
|
|
761
|
+
|
|
762
|
+
## Contribuir
|
|
340
763
|
|
|
341
|
-
|
|
764
|
+
Las contribuciones son bienvenidas. Por favor, lee las siguientes guías antes de contribuir.
|
|
342
765
|
|
|
343
|
-
|
|
766
|
+
### Configuración del Entorno
|
|
767
|
+
|
|
768
|
+
```bash
|
|
769
|
+
git clone https://github.com/nicvazquezdev/hispano-lang.git
|
|
770
|
+
cd hispano-lang
|
|
771
|
+
npm install
|
|
772
|
+
npm test
|
|
773
|
+
```
|
|
344
774
|
|
|
345
|
-
|
|
346
|
-
2. **Crea** un nuevo issue con:
|
|
347
|
-
- Descripción clara del problema
|
|
348
|
-
- Código que reproduce el error
|
|
349
|
-
- Versión de Node.js
|
|
350
|
-
- Sistema operativo
|
|
351
|
-
- Pasos para reproducir
|
|
775
|
+
### Flujo de Trabajo
|
|
352
776
|
|
|
353
|
-
|
|
777
|
+
1. Fork del repositorio
|
|
778
|
+
2. Crear rama feature: `git checkout -b feature/nueva-funcionalidad`
|
|
779
|
+
3. Commit de cambios: `git commit -m 'Añadir nueva funcionalidad'`
|
|
780
|
+
4. Push a la rama: `git push origin feature/nueva-funcionalidad`
|
|
781
|
+
5. Crear Pull Request
|
|
354
782
|
|
|
355
|
-
|
|
783
|
+
### Estándares de Código
|
|
356
784
|
|
|
357
|
-
|
|
785
|
+
- Ejecutar `npm run lint` antes de commit
|
|
786
|
+
- Ejecutar `npm run format` para formatear código
|
|
787
|
+
- Añadir tests para nuevas funcionalidades
|
|
788
|
+
- Mantener cobertura de tests existente
|
|
358
789
|
|
|
359
|
-
|
|
790
|
+
### Reportar Bugs
|
|
360
791
|
|
|
361
|
-
|
|
362
|
-
- 📧 Email: [nicorvazquezs@gmail.com](mailto:nicorvazquezs@gmail.com)
|
|
792
|
+
Abre un [issue](https://github.com/nicvazquezdev/hispano-lang/issues) incluyendo:
|
|
363
793
|
|
|
364
|
-
|
|
794
|
+
- Descripción del problema
|
|
795
|
+
- Código para reproducir
|
|
796
|
+
- Comportamiento esperado vs actual
|
|
797
|
+
- Versión de Node.js y sistema operativo
|
|
365
798
|
|
|
366
|
-
|
|
367
|
-
- 🧪 **Contribuidores y testers del proyecto**
|
|
368
|
-
- 📚 **Educadores que usan HispanoLang en sus clases**
|
|
369
|
-
- 🎓 **Estudiantes que aprenden programación con HispanoLang**
|
|
799
|
+
---
|
|
370
800
|
|
|
371
|
-
##
|
|
801
|
+
## Licencia
|
|
372
802
|
|
|
373
|
-
|
|
374
|
-
- 📦 **NPM package** listo para instalación global
|
|
375
|
-
- 🔧 **CLI tool** con modo interactivo
|
|
376
|
-
- 📝 **TypeScript support** con definiciones incluidas
|
|
377
|
-
- 🌍 **100% en español** para educación sin barreras
|
|
803
|
+
Distribuido bajo la Licencia MIT. Ver [LICENSE](LICENSE) para más información.
|
|
378
804
|
|
|
379
805
|
---
|
|
380
806
|
|
|
381
|
-
|
|
807
|
+
## Autor
|
|
382
808
|
|
|
383
|
-
|
|
809
|
+
**Nicolas Vazquez**
|
|
810
|
+
|
|
811
|
+
- GitHub: [@nicvazquezdev](https://github.com/nicvazquezdev)
|
|
812
|
+
- Email: nicorvazquezs@gmail.com
|
|
384
813
|
|
|
385
|
-
|
|
814
|
+
---
|
|
386
815
|
|
|
387
|
-
|
|
816
|
+
<p align="center">
|
|
817
|
+
<sub>Hecho con dedicación para la comunidad hispanohablante</sub>
|
|
818
|
+
</p>
|
|
388
819
|
|
|
389
|
-
|
|
820
|
+
<p align="center">
|
|
821
|
+
<a href="https://github.com/nicvazquezdev/hispano-lang">
|
|
822
|
+
<img src="https://img.shields.io/github/stars/nicvazquezdev/hispano-lang?style=social" alt="GitHub Stars"/>
|
|
823
|
+
</a>
|
|
824
|
+
</p>
|