sábado, 17 de agosto de 2013

miniSL parte 21 - Lectura de números

Como ya adelanté en la entrada anterior, hoy vamos a ver cómo leer números. La función responsable de esto es ReadNumber().

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 en la entrada