Search code examples
parsingragel

Parsing an integer and HEX value in Ragel


I am trying to design a parser using Ragel and C++ as host langauge. There is a particular case where a parameter can be defined in two formats :

a. Integer : eg. SignalValue = 24
b. Hexadecimal : eg. SignalValue = 0x18

I have the below code to parse such a parameter :

INT = ((digit+)$incr_Count) %get_int >!(int_error); #[0-9]
HEX = (([0].'x'.[0-9A-F]+)$incr_Count) %get_hex >!(hex_error); #[hexadecimal]

SIGNAL_VAL = ( INT | HEX ) %/getSignalValue;

However in the above defined parser command, only the integer values(as defined in section a) gets recognized and parsed correctly. If an hexadecimal number(eg. 0x24) is provided, then the number gets stored as ´0´ . There is no error called in case of hexadecimal number. The parser recognizes the hexadecimal, but the value stored is '0'.

I seem to be missing out some minor details with Ragel. Has anyone faced a similar situation?

The remaning part of the code :

 //Global 
int lInt = -1;


action incr_Count {
   iGenrlCount++;
}

action get_int {
  int channel = 0xFF;
  std::stringstream str;  
  while(iGenrlCount > 0)
  {
    str << *(p - iGenrlCount);
    iGenrlCount--;
  }
  str >> lInt; //push the values
  str.clear();
}


action get_hex {
 std::stringstream str; 
 while(iGenrlCount > 0)
 {
  str << std::hex << *(p - iGenrlCount);
  iGenrlCount--;
 }
 str >> lInt; //push the values
}

action getSignalValue {
  cout << "lInt = " << lInt << endl;
}

Solution

  • It's not a problem with your FSM (which looks fine for the task you have), it's more of a C++ coding issue. Try this implementation of get_hex():

    action get_hex {
     std::stringstream str;
     cout << "get_hex()" << endl;
     while(iGenrlCount > 0)
     {
      str << *(p - iGenrlCount);
      iGenrlCount--;
     }
     str >> std::hex >> lInt; //push the values
    }
    

    Notice that it uses str just as a string buffer and applies std::hex to >> from std::stringstream to int. So in the end you get:

    $ ./a.out 245
    lInt = 245
    $ ./a.out 0x245
    lInt = 581
    

    Which probably is what you want.