dewey has asked for the wisdom of the Perl Monks concerning the following question:

Hey all,

I'm working on an implementation of JOY programming language for fun (I highly recommend the language and would love to discuss it with other monks!)

My current task: I'm splitting up an input file into a list of tokens. I've slurped the whole thing into a string and am trying to split it.

The string should be split at each whitespace (\s+) unless the space is between unescaped parentheses. There will only one level of parentheses, so no need to worry about deep nesting.
For example,
this is (some more) JOY code
should split into
"this", "is", "(some more)", "JOY", "code"
I thought I had a good solution: split on whitespace when we can look behind for a ) and ahead for a (.
# match when between unescaped reverse parens + # ..or start/end of string + @script = split / (?<= #lookbehind (only remove whitespaces) + (^| #for start of string or + (?<!\\) \) ) #unescaped rparen followed by + .*? #stingy other chars + ) \s+ #some spaces, to be removed + (?= #lookahead + .*? #stingy other chars + ($| #end of string or + (?<!\\) \( ) #unescaped lparen + ) /xs, $script;
but when I run this, I get "Variable length lookbehind is not implemented in regex".

So, what would you do? I'm not sure it's possible with regular expressions anymore (a challenge!) since lookbehind was my way of not removing anything but the whitespace... should I keep regex hacking, or move on?

Thanks,

~dewey

Replies are listed 'Best First'.
Re: Splitting on unusual regex
by BrowserUk (Patriarch) on May 14, 2007 at 03:24 UTC
      Yeah, you're right that I should abandon split and this nearly works-- the one thing (which may have been unclear above) is that I'd like it to ignore escaped parentheses, so that
      ( some stuff\) )
      is not split up. I'm working on a variation that ignores \) and \( and will fit into my code like this:
      for ($script =~ m[( (?: \( [^)] + \) ) | \S+)]gx) { push @script, $_; }

      ~dewey

        Something like this?

        #! perl -slw use strict; my $code = <<EOC; This is some JOY code This is (some more) JOY code And this is some JOY code with escaped \\( and \\) like (this \\) and \\(this) and \\) EOC print for $code =~ m[ ( (?: \( (?: \\[()] | [^()] )+ \) ) | \S+ ) ]gx; __END__ C:\test>615217 This is some JOY code This is (some more) JOY code And this is some JOY code with escaped \( and \) like (this \) and \(this) and \)

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Splitting on unusual regex
by naikonta (Curate) on May 14, 2007 at 02:44 UTC
    should I keep regex hacking, or move on?
    For exercising, go ahead with regex hacking. However, if you find yourself in hard way to get it right, or you tend to solution oriented, then CPAN comes to mind: Parse::RecDescent, Text::ParseWords, Text::Balanced, to name a few.

    Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!

      Cool, I'll keep those in mind.

      ~dewey