Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

[REBOL] Re: Problems with parsing

From: brett:codeconscious at: 30-Nov-2001 11:41

Hi Peter,
> Any suggestions on how to make a parse rule for text > NOT including a special pattern? > >Crystal clear?!?
Somewhat. It would be better to provide an example, because now I have to show the solution *and* design an example :) I have come across this sort of problem a few times and I thank Ladislav for showing me a solution. One example where you might do this is when you have a sub rule that might consume something needed by an enclosing rule. For my example, I'll parse a block rather than text but the concept still applies. I want to parse the following block, and print out every word, but if I encounter a "|" I'll print out the text ********** : my-block: [ the quick brown fox | jumped | over the lazy] This next bit of code will not work. If you try it you will see that there are no "*"s printed, instead you will see the "|": single-word: [set item word! (print mold item)] phrase: [some single-word] parse my-block [ phrase some ['| (print "**********") phrase] ] The thing to note is that | is a word too. Therefore the "|" is "consumed" by the rule called SINGLE-WORD. So one way to solve this is to give SINGLE-WORD some indigestion (make it fail) when it encounters a "|". To do this I will use a dynamic rule - a rule that is modified as parse is executing. To force a rule to fail, make sure it cannot match anything any more. A way to ensure this is to skip past the end of the input. This next rule is guaranteed to fail every time: always-fails: [to end skip] Using this I now wrap SINGLE-WORD with a rule I call WORD-EXCEPT-BAR. The purpose of this new rule is to fail if it finds the "|" word otherwise it goes ahead and runs SINGLE-WORD. I also need to modify PHRASE to call WORD-EXCEPT-BAR: The dynamic rule I mentioned earlier is called WEB. Here are rules with the complex one split over multiple lines to improve readability: phrase: [some word-except-bar] word-except-bar: [ [ '| (web: :always-fails) | (web: :single-word) ] web ] To finish off I'll create a function to call parse with the correct rule and wrap the whole lot in an object just to be tidy: word-parsing-object: context [ always-fails: [to end skip] single-word: [set item word! (print mold item)] word-except-bar: [ ['| (web: :always-fails) | (web: :single-word)] web ] phrase: [some word-except-bar] set 'parse-words func[ a-block [block!] ] [ parse my-block [ phrase some ['| (print "**********") phrase] ] ] ] Here is a test run:
>> parse-words [the quick brown fox | jumped | over the lazy]
the quick brown fox ********** jumped ********** over the lazy == true HTH Brett.