[ragel-users] Re: parsing a netstring

Chuck Remes cremes.devl... at mac.com
Wed Oct 10 15:49:48 UTC 2007


Adrian,

thanks for the reply. It's encouraging to have my guesses confirmed.

I'm still a bit fuzzy on the last piece regarding error actions.

Let's use the example I contrived from the original email:


> get_size = ( digit @store_size @err(size_error) )+;
>

I'm interpreting your comment to mean that @err(size_error) will  
*only* get called if the get_size machine receives an input it isn't  
configured to handle. For example, if it receives an alphanumeric  
then action size_error will be called to handle it.

cr

On Oct 9, 2007, at 4:10 PM, Adrian Thurston wrote:

> Hi Chuck,
>
> Yes, using fnext to call out of the string consuming machine is one  
> way
> to do it. The code looks good to me.
>
> As you said you can use conditions as well. I think one of the  
> examples
> in the manual deals with variable length fields. So there is that  
> route.
>
> And also yes, you can modify p to jump ahead of the area. Just be
> mindful of jumping past pe. If you have all the data at once this  
> isn't
> a problem, but if you get your data in blocks then you have to  
> watch out
> and hack in some solution.
>
> With error actions you have to keep in mind that the operators have
> slightly different meanings because they select states as opposed to
> transitions. The error action embedding operators let you handle the
> case of 'no transition' in the states they select.
>
> Adrian
>
> Chuck Remes wrote:
>> I'm suddenly finding all sorts of uses for ragel!
>>
>> I want to write a parser for netstrings. The definition of a
>> netstring is pretty simple. It comes in the following format:
>>
>> size_in_decimal':''string array size_in_decimal bytes long'','
>>
>> I wrote a machine to parse through this and capture every byte, but
>> I'm unclear how to terminate my get_string machine. Right now I have
>> it call the action store_string as a finishing action for each byte
>> processed. The action stores the byte and increments a counter
>> variable. When the counter variable exceeds the number of bytes to be
>> processed, I want to advance out of that machine and move to the next
>> machine to confirm the byte array was terminated properly.
>>
>> I'm not sure I'm doing this correctly. From the docs (section 6.5) it
>> appears using a 'semantic condition' would make sense here, but that
>> part of the documentation is unclear to me so I'm using this
>> alternate methodology. Am I on the right track? Also, is there a way
>> to skip 'N' bytes forward instead of copying them one by one into a
>> new array (super slow!)? I'm thinking I can directly modify the 'p'
>> variable but I'm not sure this is the right way.
>>
>> Secondly, I'm not sure how to capture errors. I'm already using the
>> form '@action' to do some work in a machine. Can I specify an error
>> action using the same operator in the same machine? E.g - get_size =
>> ( digit @store_size @err(size_error) )+;
>>
>> Thanks for any input. My sample machine is listed below.
>>
>> %%{
>> 	machine parse_netstring;
>>
>> 	# snipped out some actions for the sake of brevity
>>
>> 	action store_size {
>> 		size = ( size * 10 ) + fc; # accumulate string length
>> 	};
>>
>> 	action alloc_buffer {
>> 		buffer = Array.new(size);
>> 		i = 0;
>> 	};
>>
>> 	action store_string {
>> 		buffer[i] = fc;
>> 		i = i + 1;
>> 		fnext get_string_terminator if i > size;
>> 	};
>>
>> 	get_size = ( digit >validate_not_zero ) . ( digit @store_size )*;
>>
>> 	get_delimeter = ( ':' @alloc_buffer );
>>
>> 	get_string = ( any @store_string )*;
>>
>> 	get_netstring_terminator = ',' @finalize;
>>
>> 	main := get_size . get_delimeter . get_string;
>> }%%
>>
>> >>
>>
>



More information about the ragel-users mailing list