0

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;
}
gst
  • 1,251
  • 1
  • 14
  • 32
  • Have you tried to invert INT and HEX in your definition? I suspect that ragel does not take the longest match but the first one. – Bentoy13 Aug 18 '17 at 12:50
  • @Bentoy13 : what exactly do you mean by inventing my own INT and HEX.? I have tried `INT = (([0-9]+)$incr_Count) %get_int` and it didn't work – gst Aug 18 '17 at 12:59
  • Sorry it was not clear. Try this: `SIGNAL_VAL = ( INT | HEX ) %/getSignalValue;` – Bentoy13 Aug 18 '17 at 13:03
  • @Bentoy13 : Sorry, but I did not get your idea. Your last comment is the same as what I have already done in my existing code. – gst Aug 18 '17 at 13:06
  • I am very sorry, I'm doing two things at the same time. Let's make it right: `SIGNAL_VAL = ( HEX | INT ) %/getSignalValue;` – Bentoy13 Aug 18 '17 at 13:13
  • `SIGNAL_VAL = ( HEX | INT ) %/getSignalValue;` - tried with this but same behaviour still exists. :( – gst Aug 18 '17 at 13:19
  • Sorry, it was just an idea. I cannot find a equivalent of word boundary, to force the `INT` definition to not match on `0x18`. Another idea would be to add an extra character in the definition of `INT`, like `space`, but I'm not sure it will work in all cases. – Bentoy13 Aug 18 '17 at 13:33

1 Answers1

0

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.

Roman Khimov
  • 4,807
  • 1
  • 27
  • 35