CELL& Script::ReadNumber(ISTREAM& i) {
Lo primero es leer un número hasta donde podamos leer. Iremos metiendo lo leído en la cadena s.
STRING s; while(unsigned(i.peek())<256 && isdigit(i.peek()) && i.good()) s+=i.get();
Si hemos llegado hasta una “x” o “X”, probablemente sea un número hexadecimal. Comprobaremos que empiece por “0x” o “0X” y pasamos a incorporar los dígitos hexadecimales en la variable s.
if(i.peek()=='x' || i.peek()=='X') { if(s.compare(L"0")!=0) throw L"Hexadecimal numbers must begin with 0x"; s+=i.get(); while(unsigned(i.peek())<256 && isxdigit(i.peek()) && i.good()) s+=i.get(); }
Ahora tenemos el número leído y, si no ha habido error, vamos a convertirlo en un valor. Para eso vamos a usar la función wcstoul() que detecta automáticamente si el número empieza por “0x” o es decimal.
if(i.bad()) throw L"Error while reading a number"; wchar_t* e; int value=wcstoul(s.c_str(), &e, 0);
La función wcstoul() devuelve en la variable e el puntero al primer carácter que no formaría parte del número. Este puntero deberá dirigirse al final de la cadena y si no es así, ha ocurrido algo raro.
if(e!=s.c_str()+s.size()) throw L"Invalid number";
Por otra parte, si todo va bien, usamos CreateInteger() para generar la celda con el entero correspondiente.
return CreateInteger(value); }La función CreateInteger() es muy simple. Crea una celda de tipo INT_LIT usando la función CreateCell() y le asigna el valor designado para el entero.
CELL& CreateInteger(int val) { CELL& c=CreateCell(INT_LIT); c.int_val=val; return c; }
En la próxima parte de esta serie del lenguaje MiniSL vamos a ver cómo analizar sintácticamente las expresiones primarias. Estas expresiones son las que no están formadas por otras expresiones por lo que no hay ambigüedad posible en su análisis.
0 comentarios:
Publicar un comentario