Added another improvement to this converter: "word not in keywords" feature. This is becoming interesting!

This is an updated code that tries many queries with a simple expression validation included:

#!perl -w my @data = <DATA>; for my $test ( # ( "olive&(popeye|bluto)", "(tom&jerry)|(sylvester&tweety)", "moe&(shemp|curly|joe)&larry", "moe curly larry", # "&" is optional "moe&!curly&larry", # curly not present "moe ( shemp | curly | joe ) larry", # "|" is required "jerry -tom", # standard way of "AND" and "AND NOT"... "(moe)((shemp)|(curly)|(joe))(larry)", # also this "tom&jerry|sylvester&tweety", # use re's default precedence "moe(&shemp|curly|joe)&larry", # error: "(&" instead of "&(" "moe ( shemp | curly | joe", # error: missing ")" "moe ) curly ( larry", # invalid: bad grouping "(olive)&(popeye|(bluto|brutus)))", # error: extra ")" "(jerry)((tweety))( )", # error: empty group "jerry||tweety", # error: empty word "olive - (bluto | brutus)", # only words can be excluded "olive - bluto - brutus", # Ok, spaces ignored. "(curly|!larry)&!moe", # valid, but senseless OR "moe&!(!curly)&larry", # error: curly present? "tom -!jerry" # error: don't try... # )[(shift)-1] ) { print "\n\n$test\n::\n"; (print("ERROR: Invalid expression\n") , next) if $test =~ /[^a-z\s\&\|\(\)\!\-]|^\s*[\&\|]|[\&\|]\s*$|[\&\|\(]\s +*[\&\|\)]|[\!\-]\s*[^a-z\s]/; # not_valid_chars |op_begins | op_ends | no_consec +utive_ops| negated_operator my $pars = $test; my $i = 0; $i++ while $pars =~ s/\((.*?)\)/$1/; (print("ERROR: Unpaired $1 of other $i pairs found\n") , next) if $pars =~ /([\(\)])/; my $expr = $test; $expr =~ s/([!\-]?)\s*(\w+)/($1?"(?!":"(?=").".*\\b$2\\b)"/ge; $expr =~ s/[\&\s]//g; $expr = "^($expr)"; print "$expr\n::\n"; print grep /$expr/, @data; } __DATA__ tom,jerry jerry,tom jerry,tomas sylvester,tweety tweeter,sylvester tom,sylvester popeye,olive olive,brutus moe,larry shemp,curly,joe larry,moe larry,curly,moe

To try just one of the queries, remove the comment's chars from the for at the begining, and give a number (starting from 1) as an argument in the command line.

I also removed the captures while building the regexp because them aren't used. I've just put them there for clarification.

The validation code is simple because the allowed syntax is simple too, and is very tied to regular expressions.

BTW, is there a better way to write the lines to check for parity of parentheses?


In reply to Re^2: AND and OR on Regular Expressions by vitoco
in thread AND and OR on Regular Expressions by vitoco

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.