[ragel-users] Re: Scanners inside of scanners? A better way to avoid conflicts?

Jason Garber j... at jasongarber.com
Tue Jun 17 14:12:39 UTC 2008

Thanks for the help, Erich.

Pardon my ignorance, but how shall I run the three Ragel machines from  
a C function?  Can I run them within the same processing loop or do I  
have to make a new Ragel file with its own main machine and call  
that?  If it needs its own machine, then I have to return several  
pieces of captured information, but if it can stay in the same  
processing loop, then I can just set things in the existing hash.

Sorry if I haven't explained it well enough.  I'm on Skype and AIM if  
you're willing: JasonGarberEMU

On Jun 17, 2008, at 1:04 AM, Erich Ocean wrote:

> Jason,
> Basically, you need one-token lookahead for that, which a straight
> regex can't do. You might be able to use manual state transitions, but
> it's easier to just separate the logic out into another function.
> For example, you could capture the inner contents of the emphasized
> string into a buffer and then call into a C function where you can run
> the three (Ragel) machines in sequence, in the priority order you've
> set. Use the first one that works and return into your original
> scanner machine/function. Order them longest-match-first. :-)
> Best, Erich
> On Jun 16, 2008, at 8:15 PM, Jason Garber wrote:
>> In RedCloth, we have a problem where an _emphasized_ bit of text can
>> have _(myclass#myid)a CSS class and/or id_ but shouldn't have a
>> class or id if the whole emphasis is in parentheses _(practically
>> speaking)_.  Consider this example (simplified):
>> in: "before _(in parens)_ after"
>> expected: "<p>before <em>(in parens)</em> after</p>"
>> but was: "<p>before <em class=\"in parens\">in parens)</em> after</ 
>> p>"
>> It simultaneously pursues the possibilities that the parenthesized
>> text is the class and that it's just regular parenthesized text
>> inside the em.  When the class possibility doesn't work out, the
>> final state is the regular text part but the class has already been
>> captured.
>> C = "(" ( [^)#]+ >A %{ STORE(class) } )? ("#" [^)]+ >A %
>> {STORE(id)} )? ")"
>> mtext = ( chars (mspace chars)* ) ;
>> em = "_" >X C? mtext >A %T :> "_" ;
>> # The >X resets the register from the last match, >A registers the
>> beginning of a string and the STORE saves it away.
>> I tried having the class info get written to a buffer that was then
>> captured with a leaving action, which works for the class part, but
>> I again run into the same problem with capturing the text because
>> the right side of the union matches also, so it captures too much
>> text.  Whichever side of the vertical pipe writes last, wins.
>> C = "(" ( [^)#]+ >A %{ STORE(class_buf) } )? ("#" [^)]+ >A %
>> {STORE(id_buf)} )? ")"
>> C_mtext = (C %{ STORE_ATTRIBUTES(); } mtext >A %{STORE(text)} |
>> mtext >B %{ STORE_B(text); });
>> # SET_ATTRIBUTES copies the attributes from their buffers and stores
>> them where they belong.
>> results in...
>> expected: "<p><span class=\"myclass\">SPAN</span></p>"
>> but was: "<p><span class=\"myclass\">(myclass)SPAN</span></p>"
>> Really what I want is for it to try the first pattern (with the C)
>> and, if that fails, try the second (the plain ol' mtext).  Sounds
>> like a scanner to me.  Problem is, I'm already inside a scanner, so
>> it won't let me call a scanner from within a pattern.
>> Got any ideas?
>> Jason
> >

More information about the ragel-users mailing list