# Make MyLogicalExpand

The function by Mathematica to expand a formulation with ANDS, ORS, NOT, XOR, and others, is LogicalExpand, let see an example:

LogicalExpand[ p && (q || x)]
(p && q) || (p && x)


I want to make the same thing but with strings, and these strings can be regular expression (it's contains parenthesis in some cases). I mean the form of the strings. Let set a test case.

expr = "(?i)god && (evil || salvation(.) )"
MyLogicalExpand[ expr ]


And the result should be:

"(?i)god && evil || (?i)god && salvation(.)"


Notice that result don't group the atomic expression with parenthesis and the regular expression are the same.

I don't know which way I should take. It's a parser problem, and the regular expression make it more complex, some space after o before inside atomic expressions could be appear.

How do you program MyLogicalExpand method ?

-
Why mix logical operators inside regular expressions? What does "(?i)god && (evil || salvation(.) )" mean? A string cannot match both "god" and ("evil" or "salvation")? – asterix314 Oct 14 '13 at 4:03
That's not have any sense, just is a string expression compound by others string than could be regular expression. The matter is that its class of string expression could have parenthesis, not for the task to logical expand. – jonaprieto Oct 14 '13 at 4:29

 MyLogicalExpand[expr_] :=
With[{patt = "(" ~~ x : (Except[Characters["()"]] ..) ~~ ")" /; (
Implies[#, ! #2] & @@ (
MemberQ[StringPosition[x, LetterCharacter][[;; , 1]], #] & /@ {2, 1}))
},
Module[{
cas = StringCases[expr, patt],
pos = StringPosition[expr, patt], n},
n = Length@cas;

Composition[
StringReplace[#, Table[("Mark" <> ToString[i]) -> cas[[i]], {i, n}]] &,
ToString,
LogicalExpand,
ToExpression,
StringReplacePart[#, Table["Mark" <> ToString[i], {i, n}], pos] &
][expr]
]]


The following method has couple od points which need to be improved, e.g I assumed that the expresion within ( ) is RegEx when 3rd character is LetterCharacter implies 2nd character is LetterCharacter which is just my observation. Also, markers are not so uniqe with this form.

The method is just to replace found RegExes with markers, and use LogicalExpand on converted expresion, then replace back markers with RegExes.

expr = "(?i)god &&(evil || salvation(.) )"

MyLogicalExpand@expr

"(evil && (?i)god) || ((?i)god && salvation(.))"


I don't know why you want to skip () but if you need you can add a line to Composition:

Composition[
StringReplace[#, Table[("Mark" <> ToString[i]) -> cas[[i]], {i, n}]] &,
(*new line*)StringReplace[#, "(" | ")" -> ""] &,
ToString,
LogicalExpand,
ToExpression,
StringReplacePart[#, Table["Mark" <> ToString[i], {i, n}], pos] &
][expr]

MyLogicalExpand@expr

"evil && (?i)god || (?i)god && salvation(.)"

-
@d555 I don't think that it is possible to distinguish your expression in ( ) from every possible RegularExpression object. I can improve my code if you, for example, agree to use () only for regex and other will be [] or {}. – Kuba Oct 14 '13 at 8:38
Yes, you're right. I think that It's better if I handled it with RegularExpression's Head inside the string. – jonaprieto Oct 14 '13 at 17:11