home *** CD-ROM | disk | FTP | other *** search
/ Solo Programadores 22 / SOLO_22.iso / disk22 / compila / lexico.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-16  |  10.3 KB  |  337 lines

  1. //-------------------------------------------------------------------------//
  2. //     Analizador léxico de LETRA, Solo Programadores (Enero 1996)        //
  3. //-------------------------------------------------------------------------//
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <ctype.h>
  9.  
  10. //-------------------------------------------------------------------------//
  11. //      Constantes                                                         //
  12. //-------------------------------------------------------------------------//
  13.  
  14. #define long_linea 1024         // Longitud máxima de las líneas del fuente
  15.  
  16. #define _tab 9
  17. #define _cr  13
  18. #define _lf  10
  19.  
  20. //-------------------------------------------------------------------------//
  21. //    Prototipos de funciones                           //
  22. //-------------------------------------------------------------------------//
  23.  
  24. void inicializacion_lexica (char*);
  25. void finalizacion_lexica (char*);
  26. void obtener_pieza (void);
  27.  
  28. void traer_caracter (void);
  29.  
  30. void leer_palabra (void);
  31. void leer_entero (void);
  32. void leer_etiqueta (void);
  33. void leer_literal (char);
  34.  
  35. int es_alfanumerico (char);
  36. int es_alfabetico (char);
  37. int es_numerico (char);
  38.  
  39. //-------------------------------------------------------------------------//
  40. //      Definición de las piezas sintácticas del lenguaje Letra            //
  41. //-------------------------------------------------------------------------//
  42.  
  43. enum t_piezas {            // Diferentes piezas sintácticas del lenguaje
  44.  
  45.     // Palabras reservadas del lenguaje
  46.  
  47.     p_datos,p_cierto,p_falso,p_si,p_sino,p_fin,p_mientras,
  48.     p_repetir,p_hasta,p_ir,p_hacer,p_volver,p_y,p_o,p_no,
  49.  
  50.     // Nombres de las funciones especiales
  51.  
  52.     p_borrar_pantalla,p_escribir,p_leer_tecla,p_mover_cursor,
  53.     p_color,p_aleatorio,p_esperar,p_leer_caracter,p_poner_caracter,
  54.  
  55.     // Símbolos del lenguaje
  56.  
  57.     p_distinto,p_igual,p_mayor,p_mayor_igual,p_menor,p_menor_igual,
  58.     p_mas,p_menos,p_multiplicar,p_dividir,p_modulo,p_abrir_corchete,
  59.     p_cerrar_corchete,p_abrir_parentesis,p_cerrar_parentesis,
  60.     p_dos_puntos,p_coma,
  61.  
  62.     // Piezas especiales
  63.  
  64.     p_identificador,p_etiqueta,p_entero,p_literal,p_eof,p_error};
  65.  
  66. //---------------------------------------------------------------------------//
  67. // Ahora definimos las diferentes piezas en el mismo orden, las palabras     //
  68. // reservadas se definen para poder identificarlas, el resto solo se definen //
  69. // con el fin de informar de su presencia en el listado generado.            //
  70. //---------------------------------------------------------------------------//
  71.  
  72. char * piezas[]= { "datos","cierto","falso","si","sino","fin","mientras",
  73.            "repetir","hasta","ir","hacer","volver","y","o","no",
  74.  
  75.            "borrar_pantalla","escribir","leer_tecla","mover_cursor",
  76.            "color","aleatorio","esperar","leer_caracter",
  77.            "poner_caracter",
  78.  
  79.            "distinto","igual","mayor","mayor o igual","menor",
  80.            "menor o igual","más","menos","multiplicar","dividir",
  81.            "módulo","abrir corchete","cerrar corchete","abrir paréntesis",
  82.            "cerrar paréntesis","dos puntos","coma",
  83.  
  84.            "identificador","etiqueta","entero","literal",
  85.            "--- fin del fichero ---","*** PIEZA ERROREA ***" };
  86.  
  87. //-------------------------------------------------------------------------//
  88. //    Variables globales                              //
  89. //-------------------------------------------------------------------------//
  90.  
  91. long linea;                     // Número de línea que está siendo analizada
  92.  
  93. int pieza_actual;               // Ultima pieza sintáctica analizada
  94.  
  95. char nombre[long_linea];        // Para el paso de información adicional
  96.  
  97. char * fuente;            // Puntero al fichero fuente cargado
  98.  
  99. long long_fuente;               // Longitud del fichero fuente
  100.  
  101. char * indice;                  // Indice de lectura del fichero
  102.  
  103. int error_lexico;               // Indica el tipo de error lexico producido
  104.  
  105. //-------------------------------------------------------------------------//
  106. //      Inicialización del analizador léxico                               //
  107. //-------------------------------------------------------------------------//
  108.  
  109. void inicializacion_lexica (char * fichero) {
  110.  
  111. FILE * ff;            // Fichero fuente (*.LT)
  112.  
  113.   // Abrimos el fichero, o emitimos un error si no pudimos
  114.  
  115.   if ((ff=fopen(fichero,"rb"))==NULL) {
  116.     printf("Error: No se pudo abrir el fichero indicado (%s).",fichero);
  117.     exit(0);
  118.   }
  119.  
  120.   // Pedimos memoria para cargar el fichero fuente
  121.  
  122.   fseek(ff,0,SEEK_END);
  123.  
  124.   long_fuente=ftell(ff);
  125.  
  126.   if ((fuente=(char *)malloc(long_fuente+1))==NULL) {
  127.     printf("Error: Memoria insuficiente.");
  128.     exit(0);
  129.   }
  130.  
  131.   fseek(ff,0,SEEK_SET);
  132.  
  133.   // Cargamos el fichero fuente
  134.  
  135.   long_fuente=fread(fuente,1,long_fuente,ff);
  136.  
  137.   fclose(ff);            // Cerramos el fichero
  138.  
  139.   *(fuente+long_fuente)=_cr;    // Añadimos un retorno de carro al final
  140.  
  141.   indice=fuente;         // Fijamos el índice de lectura del fuente
  142.  
  143.   linea=1;             // Fijamos el número de línea inicial
  144.  
  145. }
  146.  
  147. //-------------------------------------------------------------------------//
  148. //      Finalización del analisis léxico (libera la memoria)               //
  149. //-------------------------------------------------------------------------//
  150.  
  151. void finalizacion_lexica (void) {
  152.  
  153.   free(fuente);
  154. }
  155.  
  156. //-------------------------------------------------------------------------//
  157. //    Analizador léxico, obtiene la siguiente pieza del fichero          //
  158. //-------------------------------------------------------------------------//
  159.  
  160. void obtener_pieza (void) {
  161.  
  162.   traer_caracter();
  163.  
  164.   if (indice==fuente+long_fuente)
  165.     pieza_actual=p_eof;
  166.  
  167.   else if (es_alfabetico(tolower(*indice)))
  168.     leer_palabra();
  169.  
  170.   else if (es_numerico(*indice))
  171.     leer_entero();
  172.  
  173.   else switch (*indice) {
  174.  
  175.     case '.': leer_etiqueta(); break;
  176.  
  177.     case '"': leer_literal('"'); break;
  178.  
  179.     case '\'': leer_literal('\''); break;
  180.  
  181.     case '<': if (*++indice=='=') {
  182.         pieza_actual=p_menor_igual; indice++;
  183.           } else if (*indice=='>') {
  184.         pieza_actual=p_distinto; indice++;
  185.           } else pieza_actual=p_menor;
  186.           break;
  187.  
  188.     case '>': if (*++indice=='=') {
  189.         pieza_actual=p_mayor_igual; indice++;
  190.           } else pieza_actual=p_mayor;
  191.           break;
  192.  
  193.     case '=': pieza_actual=p_igual; indice++; break;
  194.  
  195.     case '+': pieza_actual=p_mas; indice++; break;
  196.  
  197.     case '-': pieza_actual=p_menos; indice++; break;
  198.  
  199.     case '*': pieza_actual=p_multiplicar; indice++; break;
  200.  
  201.     case '/': pieza_actual=p_dividir; indice++; break;
  202.  
  203.     case '%': pieza_actual=p_modulo; indice++; break;
  204.  
  205.     case '[': pieza_actual=p_abrir_corchete; indice++; break;
  206.  
  207.     case ']': pieza_actual=p_cerrar_corchete; indice++; break;
  208.  
  209.     case '(': pieza_actual=p_abrir_parentesis; indice++; break;
  210.  
  211.     case ')': pieza_actual=p_cerrar_parentesis; indice++; break;
  212.  
  213.     case ':': pieza_actual=p_dos_puntos; indice++; break;
  214.  
  215.     case ',': pieza_actual=p_coma; indice++; break;
  216.  
  217.     default: error_lexico=0; pieza_actual=p_error; indice++; break;
  218.  
  219.   }
  220. }
  221.  
  222. //-------------------------------------------------------------------------//
  223. //    Avanza espacios, tabulaciones, saltos de linea y comentarios       //
  224. //-------------------------------------------------------------------------//
  225.  
  226. void traer_caracter (void) {
  227.  
  228.   while ((*indice==' ' || *indice==_tab || *indice==_cr || *indice==';')
  229.     && indice<fuente+long_fuente) {
  230.  
  231.     if (*indice++==';') while (*indice!=_cr) indice++;  // Salta un comentario
  232.  
  233.     if (*indice==_lf) { indice++; linea++; }            // Salto de línea
  234.  
  235.   }
  236. }
  237.  
  238. //-------------------------------------------------------------------------//
  239. //      Lee una palabra, diferencia palabras reservadas e identificadores  //
  240. //-------------------------------------------------------------------------//
  241.  
  242. void leer_palabra (void) {
  243.  
  244.   int n=0;
  245.  
  246.   while (es_alfanumerico(nombre[n]=tolower(*indice))) {
  247.     n++; indice++;
  248.   } nombre[n]=0;
  249.  
  250.   pieza_actual=p_identificador;
  251.  
  252.   for (n=p_datos;n<p_distinto;n++)
  253.     if (!strcmp(nombre,piezas[n])) pieza_actual=n;
  254. }
  255.  
  256. //-------------------------------------------------------------------------//
  257. //    Lee una constante numérica entera                                  //
  258. //-------------------------------------------------------------------------//
  259.  
  260. void leer_entero (void) {
  261.  
  262.   int n=0;
  263.  
  264.   while (es_numerico(nombre[n]=*indice)) {
  265.     n++; indice++;
  266.   } nombre[n]=0;
  267.  
  268.   if (atol(nombre)<=32768) pieza_actual=p_entero;
  269.   else { error_lexico=1; pieza_actual=p_error; }
  270. }
  271.  
  272. //-------------------------------------------------------------------------//
  273. //    Lee una etiqueta                           //
  274. //-------------------------------------------------------------------------//
  275.  
  276. void leer_etiqueta (void) {
  277.  
  278.   int n=0;
  279.  
  280.   nombre[n++]='.'; indice++;
  281.  
  282.   while (es_alfanumerico(nombre[n]=tolower(*indice))) {
  283.     n++; indice++;
  284.   } nombre[n]=0;
  285.  
  286.   pieza_actual=p_etiqueta;
  287. }
  288.  
  289. //-------------------------------------------------------------------------//
  290. //    Lee un literal, delimitado entre el carácter indicado              //
  291. //-------------------------------------------------------------------------//
  292.  
  293. void leer_literal (char delimitador) {
  294.  
  295.   int n=0;
  296.  
  297.   indice++;
  298.  
  299.   while ((nombre[n]=*indice)!=delimitador && *indice!=_cr) {
  300.     n++; indice++;
  301.   } nombre[n]=0;
  302.  
  303.   if (*indice==delimitador) {
  304.     pieza_actual=p_literal; indice++;
  305.   } else { error_lexico=2; pieza_actual=p_error; }
  306. }
  307.  
  308. //-------------------------------------------------------------------------//
  309. //    Función para determinar si un carácter es alfanumérico             //
  310. //-------------------------------------------------------------------------//
  311.  
  312. int es_alfanumerico (char c) {
  313.  
  314.   return( (c>='a' && c<='z') || (c>='0' && c<='9') || c=='_' );
  315.  
  316. }
  317.  
  318. //-------------------------------------------------------------------------//
  319. //      Función para determinar si un carácter es alfabético               //
  320. //-------------------------------------------------------------------------//
  321.  
  322. int es_alfabetico (char c) {
  323.  
  324.   return( c>='a' && c<='z' );
  325.  
  326. }
  327.  
  328. //-------------------------------------------------------------------------//
  329. //    Función para determinar si un carácter es numérico                 //
  330. //-------------------------------------------------------------------------//
  331.  
  332. int es_numerico (char c) {
  333.  
  334.   return( c>='0' && c<='9' );
  335.  
  336. }
  337.