kschiess / parslet

A small PEG based parser library. See the Hacking page in the Wiki as well.
kschiess.github.com/parslet
MIT License
805 stars 95 forks source link

Having trouble with using Parslet #141

Closed ghost closed 9 years ago

ghost commented 9 years ago

On the gist below[1], I have the code I'm using to parse the Linux Kernel's usbmon text format [2]. however, it's not parsing properly. What exactly am I missing to be able to parse the second input ?

[1] https://gist.github.com/felipebalbi/b460fd7a16500aac8f46 [2] http://lxr.free-electrons.com/source/Documentation/usb/usbmon.txt

rubydesign commented 9 years ago

Looks like the error is from the first parse, it parses the "<" as the beginning of :data and then is missing the rest of the :data rule. I'd say your input doesn't match your grammar. You must always match whole rules and all the input

ghost commented 9 years ago

Actually, if I remove the second line, it all works fine :)

$ ruby usbmon.rb  
{:urb_tag=>"d5ea89a0 "@0,
 :timestamp=>"3575914555 "@9,
 :event=>"S"@20,
 :urb_type=>"C"@22,
 :direction=>"i"@23,
 :bus=>"1"@25,
 :dev_addr=>"001"@27,
 :endpoint=>"0 "@31,
 :tag=>"s"@33,
 :setup_packet=>
  {:request_type=>"a3 "@35,
   :request=>"00 "@38,
   :w_value=>"0000 "@41,
   :w_index=>"0003 "@46,
   :w_length=>"0004 "@51},
 :data_length=>"4 "@56,
 :data_tag=>"<"@58}

The data_tag is properly consumed and parsing stops. If I leave only second input around, I get:

$ ruby usbmon.rb  
/var/lib/gems/2.1.0/gems/parslet-1.7.1/lib/parslet/cause.rb:70:in `raise': Failed to match sequence (URB_TAG TIMESTAMP EVENT ADDR_WORD STATUS_WORD DATA_LENGTH DATA?) at line 1 char 38. (Parslet::ParseFailed)
        from /var/lib/gems/2.1.0/gems/parslet-1.7.1/lib/parslet/atoms/base.rb:49:in `parse'
        from usbmon.rb:92:in `<main>'

character 38 is the space after the = sign. Now does that mean that it can't consume =, that it can't consume the space or that it can't consume the 0 after the space ?

d5ea89a0 3575914555 C Ci:1:001:0 0 4 = 01050000

ghost commented 9 years ago

Hmmm, for some reason it doesn't like my data_length rule.

Failed to match sequence (URB_TAG TIMESTAMP EVENT ADDR_WORD STATUS_WORD DATA_LENGTH DATA?) at line 1 char 38.
`- Failed to match sequence (data_length:INTEGER SPACE?) at line 1 char 38.
   `- Failed to match sequence ([0-9]{1, } SPACE?) at line 1 char 38.
      `- Expected at least 1 of [0-9] at line 1 char 38.
         `- Failed to match [0-9] at line 1 char 38.

if I remove the integer 4 and remove the data_length rule it parses correctly:

$ ruby usbmon.rb 
{:urb_tag=>"d5ea89a0 "@0, :timestamp=>"3575914555 "@9, :event=>"C"@20, :urb_type=>"C"@22, :direction=>"i"@23, :bus=>"1"@25, :dev_addr=>"001"@27, :endpoint=>"0 "@31, :status=>{:status=>"0 "@33}, :data_tag=>"="@35, :data_words=>"01050000"@37}
ghost commented 9 years ago

Okay, found the problem. I was a missing a space in a much earlier rule :-)