Re: g_scanner funtions what for?



On Fri, 5 Mar 1999, Tim Janik  wrote:

> a GScanner will tokenize your text, that is, it'll return an integer
> for every word or number that appears in its input stream, following
> certain (customizable) rules to perform this translation.
> you still need to write the parsing functions on your own though.
> here's a little test program that will parse
> 
> <SYMBOL> = <OPTIONAL-MINUS> <NUMBER> ;
> 
> constructs, while skipping "#\n" and "/**/" style comments.
> ...
Thanks for the example.  I treid it and it worked so far.  Because
I had to scan also other things than floats I modified your
example but wasn't successful.  I append my code as attachment.

The code fails in scanning gchar * data.  Is there any documentation
to do that right?

Kind regards

     Andreas.
#include <glib.h>

/* some test text to be fed into the scanner */
static const gchar *test_text =
( "Datum: 02-16-1999\n"
  "Probenname: Hans_1\n"
  "Modulator f: 500.0\n"
  "Schwingkreis f: 500.0\n"
  "Schwingkreis U: 5.0\n"
  "Temperatur: 25.0\n"
  "Trigger-Delay: -400\n"
  "Punktzahl: 8192\n"
  "Messzeit: 2.0e-006\n" );

/* define enumeration values to be returned for specific symbols */
enum {
  SYMBOL_DATE   = G_TOKEN_LAST + 1,
  SYMBOL_SAMPLE = G_TOKEN_LAST + 2,
  SYMBOL_F_m    = G_TOKEN_LAST + 3,
  SYMBOL_F_s    = G_TOKEN_LAST + 4,
  SYMBOL_U_s    = G_TOKEN_LAST + 5,
  SYMBOL_TEMP   = G_TOKEN_LAST + 6,
  SYMBOL_DELAY  = G_TOKEN_LAST + 7,
  SYMBOL_N      = G_TOKEN_LAST + 8,
  SYMBOL_T      = G_TOKEN_LAST + 9
};

/* symbol array */
static const struct {
  gchar *symbol_name;
  guint  symbol_token;
} symbols[] = {
  { "Datum",          SYMBOL_DATE, },
  { "Probenname",     SYMBOL_SAMPLE, },
  { "Modulator f",    SYMBOL_F_m, },
  { "Schwingkreis f", SYMBOL_F_s, },
  { "Schwingkreis U", SYMBOL_U_s, },
  { "Temperatur",     SYMBOL_TEMP, },
  { "Trigger-Delay",  SYMBOL_DELAY, },
  { "Punktzahl",      SYMBOL_N, },
  { "Messzeit",       SYMBOL_T, }, 
  { NULL, 0, },
}, *symbol_p = symbols;

static gchar *date = NULL, *sample = NULL;
static gfloat F_m = 0, F_s = 0, U_s = 0, temp = 0, delay = 0, t = 0;
static gint  n = 0;

static guint
parse_symbol (GScanner *scanner)
{
  guint symbol;
  gboolean negate = FALSE;

  /* expect a valid symbol */
  g_scanner_get_next_token (scanner);
  symbol = scanner->token;
  if (symbol < SYMBOL_DATE ||
      symbol > SYMBOL_T)
    return G_TOKEN_SYMBOL;

  /* expect '=' */
  g_scanner_get_next_token (scanner);
  if (scanner->token != ':')
    return '=';

  /* feature optional '-' */
  g_scanner_peek_next_token (scanner);
  if (scanner->next_token == '-')
    {
      g_scanner_get_next_token (scanner);
      negate = !negate;
    }

  /* expect a float (ints are converted to floats on the fly) */
  g_scanner_get_next_token (scanner);
  if (scanner->token != G_TOKEN_FLOAT)
    return G_TOKEN_FLOAT;

  /* make sure the next token is a '\n' */
  if (g_scanner_peek_next_token (scanner) != '\n')
    {
      /* not so, eat up the non-semicolon and error out */
      g_scanner_get_next_token (scanner);
      return '\n';
    }

  /* assign value, eat the semicolon and exit successfully */
  switch (symbol)
    {
    case SYMBOL_DATE:
      date = scanner->value.v_string;
      break;
    case SYMBOL_SAMPLE:
      sample = scanner->value.v_string;
      break;
    case SYMBOL_F_m:
      F_m = negate ? - scanner->value.v_float : scanner->value.v_float;
      break;
    case SYMBOL_F_s:
      F_s = negate ? - scanner->value.v_float : scanner->value.v_float;
      break;
    case SYMBOL_U_s:
      U_s = negate ? - scanner->value.v_float : scanner->value.v_float;
      break;
    case SYMBOL_TEMP:
      temp = negate ? - scanner->value.v_float : scanner->value.v_float;
      break;  
    case SYMBOL_DELAY:
      delay = negate ? - scanner->value.v_float : scanner->value.v_float;
      break;
    case SYMBOL_N:
      n = scanner->value.v_int;
      break;  
    case SYMBOL_T:
      t = negate ? - scanner->value.v_float : scanner->value.v_float;
      break;
    }
  g_scanner_get_next_token (scanner);

  return G_TOKEN_NONE;
}

int
main (int argc, char *argv[])
{
  GScanner *scanner;
  guint expected_token;

  scanner = g_scanner_new (NULL);

  /* adjust lexing behaviour to suit our needs
   */
  /* convert non-floats (octal values, hex values...) to G_TOKEN_INT */
  scanner->config->numbers_2_int = TRUE;
  /* convert G_TOKEN_INT to G_TOKEN_FLOAT */
  scanner->config->int_2_float = TRUE;
  /* don't return G_TOKEN_SYMBOL, but the symbol's value */
  scanner->config->symbol_2_token = TRUE;

  /* load symbols into the scanner */
  while (symbol_p->symbol_name)
    {
      g_scanner_add_symbol (scanner,
			    symbol_p->symbol_name,
			    GINT_TO_POINTER (symbol_p->symbol_token));
      symbol_p++;
    }

  /* feed in the text */
  g_scanner_input_text (scanner, test_text, strlen (test_text));

  /* give the error handler an idea on how the input is named */
  scanner->input_name = "test text";

  /* scanning loop, we parse the input untill it's end is reached,
   * the scanner encountered a lexing error, or our sub routine came
   * across invalid syntax
   */
  do
    {
      expected_token = parse_symbol (scanner);
      
      g_scanner_peek_next_token (scanner);
    }
  while (expected_token == G_TOKEN_NONE &&
	 scanner->next_token != G_TOKEN_EOF &&
	 scanner->next_token != G_TOKEN_ERROR);

  /* give an error message upon syntax errors */
  if (expected_token != G_TOKEN_NONE)
    g_scanner_unexp_token (scanner, expected_token, NULL, "symbol", NULL, NULL, TRUE);

  /* finsish parsing */
  g_scanner_destroy (scanner);

  /* print results */
  g_print ("date: %s, sample: %s\n", date, sample);
  g_print ("F_m = %f, F_s = %f, U_s = %f, temp = %f, delay = %f, t = %f\n",
            F_m, F_s, U_s, temp, delay, t);
  g_print ("n = %i\n", n);
  
  return 0;
}




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]