ESTRUCTURA

src/
├── ast/
│   ├── builders/
│   │   ├── ASTBuilder.js
│   │   ├── DeclarationVisitor.js
│   │   ├── ExpressionVisitor.js
│   │   └── StatementVisitor.js
│   ├── core/
│   │   ├── ASTContext.js
│   │   ├── ASTNode.js
│   │   ├── NodeTypes.js
│   │   └── ProgramNode.js
│   ├── declarations/
│   │   ├── ArrayDeclarationNode.js
│   │   ├── ConstantDeclarationNode.js
│   │   ├── FunctionDeclarationNode.js
│   │   ├── ParameterNode.js
│   │   ├── ProcedureDeclarationNode.js
│   │   └── VariableDeclarationNode.js
│   ├── expressions/
│   │   ├── AccessNode.js
│   │   ├── BinaryExpressionNode.js
│   │   ├── FunctionCallNode.js
│   │   ├── GroupExpressionNode.js
│   │   ├── IdentifierNode.js
│   │   ├── LiteralNode.js
│   │   ├── LogicalExpressionNode.js
│   │   └── LogicalNotNode.js
│   ├── statements/
│   │   ├── AssignmentNode.js
│   │   ├── BlockNode.js
│   │   ├── CaseNode.js
│   │   ├── DefaultNode.js
│   │   ├── ForNode.js
│   │   ├── IfNode.js
│   │   ├── ProcedureCallNode.js
│   │   ├── ReadNode.js
│   │   ├── ReturnNode.js
│   │   ├── SwitchNode.js
│   │   ├── WhileNode.js
│   │   └── WriteNode.js
│   └── utils/
│       ├── ASTFactory.js
│       ├── ASTPrinter.js
│       └── CSTAdapter.js
├── interpreter/
│   └── run.js
├── lexer/
│   ├── config/
│   │   └── assignmentMode.js
│   ├── tokens/
│   │   ├── comments.js
│   │   ├── index.js
│   │   ├── keywords.js
│   │   ├── literals.js
│   │   ├── operators.js
│   │   ├── punctuation.js
│   │   ├── types.js
│   │   └── whitespace.js
│   ├── lexer.js
│   └── tokenVocabulary.js
├── parser/
│   ├── calls/
│   │   ├── functionCall.js
│   │   └── procedureCall.js
│   ├── control/
│   │   ├── if/
│   │   │   ├── elseClause.js
│   │   │   ├── elseIfClause.js
│   │   │   └── ifStatement.js
│   │   ├── forRules.js
│   │   ├── switchRules.js
│   │   └── whileRules.js
│   ├── config/
│   │   └── assignmentRules.js
│   ├── core/
│   │   ├── blockRules.js
│   │   ├── programRules.js
│   │   └── statementRules.js
│   ├── declarations/
│   │   ├── constantDeclaration.js
│   │   ├── functionDeclaration.js
│   │   ├── parameterRules.js
│   │   ├── procedureDeclaration.js
│   │   └── variableDeclaration.js
│   ├── expressions/
│   │   ├── access.js
│   │   ├── additive.js
│   │   ├── comparison.js
│   │   ├── expression.js
│   │   ├── logical.js
│   │   ├── multiplicative.js
│   │   ├── power.js
│   │   └── primary.js
│   ├── io/
│   │   ├── readStatement.js
│   │   └── writeStatement.js
│   ├── statements/
│   │   ├── assignmentStatement.js
│   │   └── returnStatement.js
│   ├── types/
│   │   └── typeRules.js
│   └── parser.js
├── errors/
│   ├── LanguageError.js
│   ├── SemanticError.js
│   └── SyntaxError.js
└── semantic/
    ├── analyzer/
    │   └── SemanticAnalyzer.js
    ├── context/
    │   └── SemanticContext.js
    ├── scopes/
    │   ├── Scope.js
    │   └── ScopeManager.js
    ├── symbols/
    │   ├── Symbol.js
    │   ├── SymbolKind.js
    │   └── SymbolTable.js
    ├── types/
    │   └── TypeSystem.js
    ├── validators/
    │   ├── DeclarationValidator.js
    │   ├── AssignmentValidator.js
    │   ├── ExpressionValidator.js
    │   ├── ArrayValidator.js
    │   ├── FunctionValidator.js
    │   ├── ProcedureValidator.js
    │   ├── ControlFlowValidator.js
    │   ├── CallValidator.js
    │   └── ReturnValidator.js
    └── rules/
        ├── ScopeRules.js
        ├── IdentifierRules.js
        ├── TypeRules.js
        ├── ArithmeticRules.js
        ├── LogicalRules.js
        ├── ComparisonRules.js
        ├── FlowRules.js
        └── IORules.js

-----------------

GRAMÁTICA

-- PROGRAMA --

programa ::= { instruccion } ;

-- INSTRUCCIONES --

instruction ::=
      constant_declaration
    | declaration
    | assignment
    | input
    | output
    | return_stmt
    | if_statement
    | while_statement
    | for_statement
    | switch_statement
    | function_def
    | procedure_def
    | procedure_call ;

-- BLOQUES --

block ::= { instruction } ;

-- VARIABLES Y TIPOS --

declaration ::=
    "Declare"
    type
    declarator
    { "," declarator } ;

declarator ::=
    identifier
    dimension_declaration ;

dimension_declaration ::= ("[" expression "]")+ ;

dimensions ::= ("[" expression "]")+ ;

constant_declaration ::=
    "Constant"
    type
    identifier
    "<-"
    expression ;

type ::=
      "Integer"
    | "Real"
    | "String"
    | "Boolean"
    | "Character" ;

-- ASIGNACIÓN --

assignment ::=
    l_value
    "<-"
    expression ;

l_value ::=
    identifier
    { "[" expression "]" } ;

-- ENTRADA / SALIDA --

input ::=
    "Read"
    identifier
    { "," identifier } ;

output ::=
    "Write"
    expression
    { "," expression } ;

-- EXPRESIONES --

eexpression ::= logical_expression ;

logical_expression ::= or_expression ;

or_expression ::=
    and_expression
    { "OR" and_expression } ;

and_expression ::=
    not_expression
    { "AND" not_expression } ;

not_expression ::=
      "NOT" not_expression
    | comparison ;

comparison ::=
    sum
    [
        ( "=" | "<>" | "<" | ">" | "<=" | ">=" )
        sum
    ] ;

sum ::=
    term
    { ("+" | "-") term } ;

term ::=
    unary
    { ("*" | "/" | "%") unary } ;

unary ::=
      "-" unary
    | "+" unary
    | power ;

power ::=
    access
    [ "^" power ] ;

access ::=
    identifier
    { "[" expression "]" } ;

primary ::=
      integer_literal
    | real_literal
    | string_literal
    | character_literal
    | boolean_literal
    | function_call
    | identifier
    | "(" expression ")" ;

-- CONDICIONALES --

if_statement ::=
    "If"
    expression
    "Then"
    block
    { else_if }
    [ else ]
    "End If" ;

else_if ::=
    "Else If"
    expression
    "Then"
    block ;

else ::=
    "Else"
    block ;

-- MIENTRAS --

while_statement ::=
    "While"
    expression
    block
    "End While" ;

-- PARA --

for_statement ::=
    "For"
    identifier
    "<-"
    expression
    "To"
    expression
    [ "Step" expression ]
    block
    "End For" ;

-- SELECCIONAR CASO --

switch_statement ::=
    "Switch"
    expression
    case_block
    { case_block }
    [ default_block ]
    "EndSwitch" ;

case_block ::=
    "Case"
    expression
    ":"
    block ;

default_block ::=
    "Default"
    ":"
    block ;

-- PROCEDIMIENTO --

procedure_def ::=
    "Procedure"
    identifier
    "(" [ parameters_list ] ")"
    block
    "EndProcedure" ;

-- FUNCIÓN --

function_def ::=
    "Function"
    type
    identifier
    "(" [ parameters_list ] ")"
    block
    "EndFunction" ;

-- PARÁMETROS --

parameters_list ::=
    parameter
    { "," parameter } ;

parameter ::=
    type
    identifier
    parameter_dimension ;

parameter_dimension ::= ("[" "]")+ ;

-- LLAMADAS --

procedure_call ::=
    "Call"
    identifier
    "(" [ arguments ] ")" ;

function_call ::=
    identifier
    "(" [ arguments ] ")" ;

arguments ::=
    expression
    { "," expression } ;

-- RETORNO --

return_stmt ::=
    "Return"
    expression ;

-- IDENTIFICADORES Y LITERALES --

identifier ::=
    letter
    { letter | digit | "_" } ;

integer_literal ::=
    digit
    { digit } ;

real_literal ::=
    digit
    { digit } ;

string_literal ::=
    '"'
    { character }
    '"' ;

character_literal ::=
      '''
    { character }
    ''' ;

boolean_literal ::=
      "true"
    | "false" ;


-----------------------------------------

Semántica

---

# Especificación semántica del lenguaje

## 1. Gestión de identificadores

# 1.2 Declaración obligatoria

Validar que ninguna variable, constante, función o procedimiento se
utilice antes de ser declarada en el código.

Correcto:

```txt
Declarar Entero edad
Constante Entero edad2

Funcion Entero suma(Entero a, Entero b)
Retornar a + b
Fin Funcion

edad <- suma(edad, edad2)
```

Incorrecto:

```txt
edad <- suma(edad, edad2)
```

```
Error:
La variable 'edad' no se ha declarado.
```

---

# 1.3 Redeclaración

Prevenir que se declaren dos identificadores con el
mismo nombre en el mismo ámbito (scope).

Correcto:

```txt
Declarar Entero edad
Constante Entero edad2
```

Incorrecto:

```txt
Declarar Entero edad
Constante Entero edad
```

```
Error:
La variable 'edad' ya ha sido declarada.
```

---

# 1.4. Constantes

Las constantes serán **inmutables**.

Ejemplo:

```txt
Constante Real pi <- 3.1416
```

Esto:

```txt
pi <- 10
```

produce:

```
Error:
No se puede modificar la constante 'pi'.
```

---

# 1.4 Inicialización de variable

Detectar si el usuario está intentando
leer una variable que ya fue declarada
pero a la cual nunca se le ha asignado
un valor (inicialización pendiente).

Correcto:

```txt
Declarar Entero a <- 10
Declarar Entero b <- a + 2
```

Incorrecto:

```txt
Declarar Entero b <- a + 2
```

```
Error:
La variable 'a' no tiene ningún valor.
```

---

# 1.5 Declaración de arreglos

Los arreglos deben tener dimensión de tipo Entero o variable.

Correcto:

```txt
Declarar Real a[2]
Declarar Real a[1 + 3]
```

Incorrecto:

```txt
Declarar Real a[2.1]
Declarar Real b[Verdadero]

```
Error:
La dimensión sólo puede ser Entero.
```

---

## 2. Sistema de tipos

# 2.1 Tipos base oficiales

Tipos primitivos:

| Tipo       | Descripción       |
| ---------- | ----------------- |
| `Entero`   | Números enteros   |
| `Real`     | Números decimales |
| `Cadena`   | Texto             |
| `Caracter` | Un solo carácter  |
| `Logico`   | Valores booleanos |

Ejemplos:

```txt
Declarar Entero edad

Declarar Real promedio

Declarar Cadena nombre

Declarar Caracter inicial

Declarar Logico activo
```

---

# 2.2 Tipado estático fuerte

Una variable tiene un tipo fijo durante toda su vida.

Ejemplo:

```txt
Declarar Entero x

x <- 10
```

Correcto.

Pero:

```txt
x <- "hola"
```

Error:

```
Error semántico:
No se puede asignar Cadena a Entero.
```

---

# 2.3 Compatibilidad entre tipos

Permitido:

```txt
"Edad: " + edad
```

Ejemplo:

```txt
Declarar Entero edad

edad <- 20

Escribir "Edad: " + edad
```

Resultado:

```
Edad: 20
```

---

La regla será:

| Operandos                         | Resultado |
| --------------------------------- | --------- |
| Entero + Entero                   | Entero    |
| Entero + Real                     | Real      |
| Real + Real                       | Real      |
| Cadena + Todos los tipos          | Cadena    |
| Logico + Entero                   | ❌ Error   |
| Logico + Real                     | ❌ Error   |

---

# 2.4 Conversión de tipos

El lenguaje tendrá **coerción limitada controlada**.

Permitido:

```txt
"Edad: " + edad
```

Regla especial:

```
Cadena + cualquier tipo = Cadena
```

---

No permitido:

```txt
5 + Verdadero
```

Error:

```
No existe conversión automática de Logico a Entero.
```

---

# 2.5 Comparaciones entre tipos

Comparaciones estrictas.

Ejemplo:

```txt
"5" > 3
```

Error:

```
No se pueden comparar Cadena y Entero.
```

Permitido:

```txt
5 > 3

"x" = "y"
```

---


# 2.6 Operaciones lógicas entre tipos

Solo aceptan:

```txt
Logico
```

Ejemplo válido:

```txt
(x > 5) Y (y < 10)
```

Incorrecto:

```txt
5 Y "hola"
```

Error:

```
El operador Y requiere operandos Logico.
```

---

# 2.7 Aritmética entre tipos

Operaciones solamente entre tipos numéricos.
Con una excepción a '+' para el uso híbrido de concatenación y suma.

Solo aceptan (exceptuando +):
```txt
Entero
Real
```

Permitido:

```txt
a <- 10 + " años"
b <- 10 / 60 + z
```

---

Incorrecto:

```txt
b <- 10 / Verdadero * "90"
```

Error:

```
No se pueden operar Entero con Logico.
```

# 3. Scope

---

## 3.1 Scope de bloques

El lenguaje tendrá scope léxico.

Ejemplo:

```txt
Mientras x < 10

    Declarar Entero temporal

Fin Mientras


Escribir temporal
```

Error:

```
La variable temporal no existe fuera del bloque.
```

---

# 3.2 Shadowing

No permitido.

Ejemplo:

```txt
Declarar Entero x


Mientras condicion

    Declarar Real x

Fin Mientras
```

Error:

```
La variable x ya existe en un scope superior.
```

# 4. Funciones y procedimientos

---

## 4.1 Argumentos obligatorios

Validar que toda llamada a una función o procedimiento envíe
exactamente la cantidad de argumentos que requiere.

Permitido:

```txt
Funcion Entero suma(Entero a, Entero b)
Retornar a + b
Fin Funcion

z <- suma(10, 20)
```

---

No permitido:

```txt
Funcion Entero suma(Entero a, Entero b)
Retornar a + b
Fin Funcion

z <- suma(20)
```

Error:

```
La cantidad de argumentos esperados no corresponde con los parámetros.
```

---

## 4.2 Tipos de argumentos

Comprobar que el tipo de cada argumento enviado en
una llamada coincida con el tipo esperado en la
definición de la función.

Permitido:

```txt
Funcion Entero suma(Entero a, Entero b)
Retornar a + b
Fin Funcion

z <- suma(10, 20)
```

---

No permitido:

```txt
Funcion Entero suma(Entero a, Entero b)
Retornar a + b
Fin Funcion

z <- suma("1", '2')
```

Error:

```
El tipo de argumento recibido no coincide con lo esperado.
```

---

## 4.3 Caminos de ejecución

Analizar que todos los flujos posibles (cada rama de un if/else)
de una función terminen en un return válido.
No puede haber "caminos muertos" que omitan devolver un valor.


Por ejemplo:

```txt
Procedimiento mostrar()

    Si Falso = Verdadero Entonces
    Retornar 10
    Fin Si

Fin Procedimiento
```

---

# 4.4 Return

Funciones:

```txt
Funcion Entero suma()

    Retornar 10

Fin Funcion
```

Obligatorio para funciones.

---

Procedimientos:

```txt
Procedimiento mostrar()

    Retornar 10

Fin Procedimiento
```

No puede tener retorno ni siquiera vacío.

Error:

```
Un procedimiento no puede retornar un valor.
```

---

# 5. Control de flujo

## 5.1 Condiciones booleanas obligatorias

No hay coerción.

Incorrecto:

```txt
Mientras 5
```

Error:

```
Mientras requiere una expresión Logica.
```

Correcto:

```txt
Mientras x < 10
```

---

## 5.2 Casos no repetidos

Validar que los casos en un switch no se repitan.

Incorrecto:

```txt
Seleccionar x > 5
    Caso 1:

    Caso 1:
Fin Seleccionar
```

Error:

```
El Caso se ha repetido.
```

Correcto:

```txt
Seleccionar x > 5
    Caso 1:

    Caso 2:
Fin Seleccionar
```

---

# 6. Entrada / salida

## 6.1 Escribir

Permite mezcla de tipos.

Ejemplo:

```txt
Escribir "Edad:", edad
```

Internamente:

```
Cadena + conversión controlada
```

---

También:

```txt
Escribir "Edad: " + edad
```

válido.

---

# 6.2 Leer

Respeta el tipo declarado.

Ejemplo:

```txt
Declarar Entero edad

Leer edad
```

El runtime espera:

```
Número entero
```

Si recibe:

```
hola
```

Error de ejecución:

```
No se puede convertir 'hola' a Entero.
```

---



-------------------------------------------------

## Especificación semántica resumida

# 1. Gestión de identificadores

### 1.1 Declaración obligatoria

* Todo identificador debe declararse antes de utilizarse.
* Aplica a variables, constantes, funciones y procedimientos.

### 1.2 Redeclaración

* No se permiten identificadores con el mismo nombre dentro del mismo ámbito.

### 1.3 Constantes

* Las constantes son inmutables.
* No pueden cambiar su valor después de ser declaradas.

### 1.4 Inicialización de variables

* Una variable debe tener un valor asignado antes de ser utilizada en expresiones.

### 1.5 Arreglos

* La dimensión de un arreglo debe ser un valor entero o una expresión que produzca un entero.

---

# 2. Sistema de tipos

### 2.1 Tipos base

Tipos primitivos soportados:

* Entero
* Real
* Cadena
* Caracter
* Logico

### 2.2 Tipado estático fuerte

* Cada variable mantiene un tipo fijo durante su existencia.
* No se permiten asignaciones incompatibles.

### 2.3 Compatibilidad entre tipos

* Entero + Entero → Entero.
* Entero + Real → Real.
* Real + Real → Real.
* Cadena + cualquier tipo → Cadena.
* Operaciones incompatibles generan error.

### 2.4 Conversión de tipos

* Solo existe conversión automática limitada.
* La concatenación con cadenas permite convertir valores a texto.
* No existe conversión automática entre tipos incompatibles.

### 2.5 Comparaciones

* Solo se pueden comparar valores de tipos compatibles.
* No se permiten comparaciones entre tipos diferentes.

### 2.6 Operadores lógicos

* Los operadores lógicos requieren operandos de tipo Logico.
* No aceptan valores numéricos o textuales.

### 2.7 Operaciones aritméticas

* Solo aceptan tipos numéricos.
* La excepción es `+`, que permite suma o concatenación.

---

# 3. Scope

### 3.1 Scope de bloques

* El lenguaje utiliza alcance léxico.
* Las variables declaradas dentro de un bloque solo existen dentro de él.

### 3.2 Shadowing

* No se permite declarar una variable con el mismo nombre que otra existente en un ámbito superior.

---

# 4. Funciones y procedimientos

### 4.1 Cantidad de argumentos

* Las llamadas deben enviar exactamente la cantidad de parámetros requerida.

### 4.2 Tipos de argumentos

* Los argumentos enviados deben coincidir con los tipos definidos en la función o procedimiento.

### 4.3 Caminos de ejecución

* Toda función debe garantizar un retorno válido en todos sus caminos posibles.

### 4.4 Return

* Las funciones deben retornar un valor.
* Los procedimientos no pueden retornar valores.

---

# 5. Control de flujo

### 5.1 Condiciones booleanas

* Las estructuras de control requieren expresiones de tipo Logico.
* No existe conversión automática de otros tipos a booleanos.

### 5.2 Casos repetidos

* Los valores de los casos dentro de un `Seleccionar` deben ser únicos.

---

# 6. Entrada / salida

### 6.1 Escribir

* Permite combinar textos con valores de cualquier tipo mediante conversión controlada.

### 6.2 Leer

* La entrada debe coincidir con el tipo declarado de la variable.
* Los valores inválidos generan errores de ejecución.
