-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparser.y
More file actions
211 lines (177 loc) · 5.59 KB
/
Copy pathparser.y
File metadata and controls
211 lines (177 loc) · 5.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "symbolTable.h"
extern FILE *yyin;
void yyerror(const char *s);
int yylex(void);
int quit_flag = 0;
int echo_enabled = 1;
void set_echo(int value) { echo_enabled = value; }
int get_echo() { return echo_enabled; }
void set_quit_flag(int value) { quit_flag = value; }
int get_quit_flag(void) { return quit_flag; }
void yyrestart(FILE *input_file);
%}
%union {
double num;
char *str;
}
%token EOL
%token QUIT_CALL
%token WORKSPACE_CALL
%token CLEAR_CALL
%token HELP_CALL
%token CLEAN_CALL
%token ECHO_ON ECHO_OFF
%token SEMICOLON
%token <str> LOAD_CALL
%token <str> ECHO_PRINT
%token <num> NUMBER
%token <str> ID
%token PLUS MINUS TIMES DIVIDE POWER
%left PLUS MINUS
%left TIMES DIVIDE
%right POWER
%right UMINUS
%type <num> expr
%type <num> assignment
%type <num> func_call
%type <num> line_end
%%
input:
/* vacío */
| input line
;
line:
assignment line_end { if (get_echo() && $2) printf("%.2f\n", $1); }
| expr line_end { if (get_echo() && $2) printf("%.2f\n", $1); }
| QUIT_CALL line_end { set_quit_flag(1); }
| WORKSPACE_CALL line_end { printWorkspace(); }
| CLEAR_CALL line_end { clearVariables(); printf("Variables eliminadas.\n");}
| HELP_CALL line_end {
printf("------ AYUDA ------\n");
printf("Este es un intérprete de expresiones matemáticas.\n");
printf("Comandos disponibles:\n");
printf(" - QUIT() : Salir del programa\n");
printf(" - HELP() : Mostrar esta ayuda\n");
printf(" - CLEAR() : Borrar todas las variables\n");
printf(" - CLEAN() : Limpiar la ventana de comandos\n");
printf(" - WORKSPACE() : Ver variables definidas\n");
printf(" - ECHO ON/OFF() : Activa o desactiva el ECHO\n");
printf("\tPara descativarlo solo para 1 comando, terminarlo con un ';'\n");
printf(" - LOAD(\"archivo.txt\") : Ejecutar comandos desde archivo\n");
printf("También puedes usar:\n");
printf(" - Variables: a = 3, a + 1\n");
printf(" - Constantes: PI, E\n");
printf(" - Operaciones básicas: +, -, *, /, ^\n");
printf(" - Funciones: sin(), cos(), log(), min() y max()\n");
printf("-------------------\n");
}
| CLEAN_CALL line_end {
system("clear"); // En Linux/macOS
}
| ECHO_ON line_end { set_echo(1); printf("ECHO activado.\n"); }
| ECHO_OFF line_end { set_echo(0); printf("ECHO desactivado.\n"); }
| LOAD_CALL line_end {
char filename[1024];
if (sscanf($1, "LOAD(\"%1023[^\"]\")", filename) != 1) {
fprintf(stderr, "Error de formato en LOAD\n");
} else {
FILE *f = fopen(filename, "r");
if (!f) {
fprintf(stderr, "Error al abrir archivo: %s\n", filename);
} else {
printf("ARCHIVO ABIERTO\n");
yyin = f;
yyrestart(yyin);
}
}
free($1);
}
| ECHO_PRINT line_end {
// Imprimir el mensaje sin las comillas
size_t len = strlen($1);
if (len >= 2 && $1[0] == '"' && $1[len - 1] == '"') {
$1[len - 1] = '\0'; // quitar última comilla
printf("%s\n", $1 + 1); // quitar primera comilla
} else {
printf("%s\n", $1); // seguridad si falta comilla
}
free($1);
}
| EOL
| error EOL { yyerror("Entrada no válida"); yyerrok; }
;
assignment:
ID '=' expr {
setVariable($1, $3);
$$ = $3;
free($1);
}
;
expr:
expr PLUS expr { $$ = $1 + $3; }
| expr MINUS expr { $$ = $1 - $3; }
| expr TIMES expr { $$ = $1 * $3; }
| expr DIVIDE expr {
if ($3 == 0) {
yyerror("División por cero");
$$ = 0;
} else {
$$ = $1 / $3;
}
}
| expr POWER expr { $$ = pow($1, $3); }
| MINUS expr %prec UMINUS { $$ = -$2; }
| '(' expr ')' { $$ = $2; }
| NUMBER { $$ = $1; }
| func_call { $$ = $1; }
| ID {
double val;
if (getVariable($1, &val)) {
$$ = val;
} else {
yyerror("Variable no definida");
$$ = 0;
}
free($1);
}
;
func_call:
ID '(' expr ')' {
double result;
if (strcmp($1, "sin") == 0) result = sin($3);
else if (strcmp($1, "cos") == 0) result = cos($3);
else if (strcmp($1, "tan") == 0) result = tan($3);
else if (strcmp($1, "log") == 0) result = log($3);
else if (strcmp($1, "exp") == 0) result = exp($3);
else {
yyerror("Función desconocida o número de argumentos incorrecto.");
result = 0;
}
free($1);
$$ = result;
}
| ID '(' expr ',' expr ')' {
double result;
if (strcmp($1, "min") == 0) result = fmin($3, $5);
else if (strcmp($1, "max") == 0) result = fmax($3, $5);
else {
yyerror("Función desconocida o número de argumentos incorrecto.");
result = 0;
}
free($1);
$$ = result;
}
;
line_end:
EOL { $$ = 1; } // mostrar resultado
| SEMICOLON { $$ = 0; } // no mostrar resultado
;
%%
void yyerror(const char *s) {
fprintf(stderr, "Error: %s\n", s);
}