Ejemplo de gramática (expresiones aritméticas): E := T + E | T - E | T T := F * T | F / T | F F ::= i | (E) FNG: E ::= iPTME | (ECPTME | iDTME | (ECDTME | iME | (ECME | iPTSE | (ECPTSE | iDTSE | (ECDTSE | iSE | (ECSE | iPT | (ECPT | iDT | (ECDT | i | (EC T ::= iPT | (ECPT | iDT | (ECDT | i | (EC F ::= i | (EC M ::= + S ::= P ::= * D ::= / C ::= ) En forma LL(1) queda: E ::= iV | (ECV V ::= *TX | /TX | +E | -E | λ X ::= +E | -E | λ T ::= iU | (ECU U ::= *T | /T | λ F ::= i | (EC C ::= ) 1 Paso automático de la gramática LL(1) al analizador: caso a) Reglas SIN λ gramática LL(1), U ::= x X1 X2 ... Xn | y Y1 Y2 ... Ym | ... | z Z1 Z2 ... Zp caso b) Reglas CON λ U ::= x X1 X2 ... Xn | ... | z Z1 Z2 ... Zp | λ int U (char *cadena, int i) { if (i<0) return i; /* Pasa errores anteriores */ switch (cadena[i]) { case x: i++; ... i = X1 (cadena, i); case z: i = X2 (cadena, i); i++; ... i = Z1 (cadena, i); i = Xn (cadena, i); i = Z2 (cadena, i); break; ... case y: i = Zp (cadena, i); i++; break; i = Y1 (cadena, i); /* Fin de cadena va a default */ i = Y2 (cadena, i); default: return -n; /* Genera error n */ ... } i = Ym (cadena, i); return i; break; } ... 2 int U (char *cadena, int i) { if (i<0) return i; /* Pasa errores anteriores */ switch (cadena[i]) { case x: i++; i = X1 (cadena, i); i = X2 (cadena, i); ... i = Xn (cadena, i); break; ... case z: i++; i = Z1 (cadena, i); i = Z2 (cadena, i); ... i = Zp (cadena, i); break; } return i; } int E (char *cadena, int i) { if (i<0) return i; switch (cadena[i]) { case 'i': i++; i = V (cadena, i); break; case '(': i++; i = E (cadena, i); i = C (cadena, i); i = V (cadena, i); break; default: return -1; } return i; } int V (char *cadena, int i) { if (i<0) return i; switch (cadena[i]) { case '*': case '/': i++; i = T (cadena, i); i = X (cadena, i); break; case '+': case '-': i++; i = E (cadena, i); break; } return i; } 3 int X (char *cadena, int i) { if (i<0) return i; switch (cadena[i]) { case '+': case '-': i++; i = E (cadena, i); break; } return i; } int U (char *cadena, int i) { if (i<0) return i; switch (cadena[i]) { case '*': case '/': i++; i = T (cadena, i); break; } return i; } int T (char *cadena, int i) { if (i<0) return i; switch (cadena[i]) { case 'i': i++; i = U (cadena, i); break; case '(': i++; i = E (cadena, i); i = C (cadena, i); i = U (cadena, i); break; default: return -2; } return i; } int F (char *cadena, int i) { if (i<0) return i; switch (cadena[i]) { case 'i': i++; break; case '(': i++; i = E (cadena, i); i = C (cadena, i); break; default: return -3; } return i; } 4 int C (char *cadena, int i) { if (i<0) return i; switch (cadena[i]) { case ')': i++; break; default: return -4; } return i; } Análisis: La cadena x se analiza invocando axioma (x, 0) En nuestro ejemplo: E (x, 0) Si devuelve strlen(x), la cadena x es correcta. En caso contrario, devolverá un número negativo que indica el error detectado. Ejemplo: análisis de "i+i*i". E ("i+i*i", 0) = V ("i+i*i", 1) = = E ("i+i*i", 2) = = V ("i+i*i", 3) = = X ("i+i*i", T ("i+i*i", 4)) = = X ("i+i*i", U ("i+i*i", 5)) = = X ("i+i*i", 5) = =5 5 Ejemplo: análisis de "i+i*". E ("i+i*", 0) = V ("i+i*", 1) = = E ("i+i*", 2) = = V ("i+i*", 3) = = X ("i+i*", T ("i+i*", 4)) = = -2 6