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

How to use present and absent? #85

Closed dongli closed 11 years ago

dongli commented 11 years ago

Hi,

I need to use present? and absent? to write atoms conditionally. The following is a test which does not work:

require "parslet"

class TestParser < Parslet::Parser
    rule(:test) {
        str('a') >> ( ( str('a').present? >> str('b') ) | ( str('a').absent? >> str('c') ) )
    }
end

p TestParser.new.test.parse('c')
begin
    TestParser.new.test.parse('ab')
rescue Parslet::ParseFailed => error
    puts error.cause.ascii_tree
end

with error output:

"c"@0
Failed to match sequence ('a'? (&'a' 'b' / !'a' 'c')) at line 1 char 2.
`- Expected one of [&'a' 'b', !'a' 'c'] at line 1 char 2.
   |- Failed to match sequence (&'a' 'b') at line 1 char 2.
   |  `- Input should start with 'a' at line 1 char 2.
   `- Failed to match sequence (!'a' 'c') at line 1 char 2.
      `- Expected "c", but got "b" at line 1 char 2.

I write atoms this way in order to balance parenthesis, for example, if the left parenthesis is absent, the right one should be absent too.

floere commented 11 years ago

Hi @dongli!

Perhaps it is best to study this example? https://github.com/kschiess/parslet/blob/master/example/parens.rb

Cheers, Florian

dongli commented 11 years ago

Hi @floere

I saw that example, but haven't grabbed the main point. So I need to use Transform stuff to achieve this?

Thanks!

Li

dongli commented 11 years ago

BTW, I am writing a Fortran parser for my purpose.

dongli commented 11 years ago

Hi @floere! To my knowledge, the Transform should only post-process the parsing result, and couldn't help parsing. Is that right?

If you have time, could you check out my little parser (https://gist.github.com/dongli/5791976) by running:

rspec --fail-fast rspec_fortran_parser.rb

Cheers, Li

floere commented 11 years ago

I should have been more specific: I was just noting an example where you can see a parser for balancing parentheses.

Your example above might be best served by str('a') >> str('b') | str('c') – in words: either (|) match an a followed by a b or a c.

dongli commented 11 years ago

I used another strategy to accomplish parentheses balancing.