Is a statement of propositional logic always true?
Retina 0.8.2, 136 124 121 bytes
{T`()`&lt;&gt;
.*P.*
&lt;$&amp; ¶ $&amp;&gt;
(?=(P'*))(?=.*\1[^P']*(¶|$))\1
$.2
¶
a
&lt;not 1&gt;|&lt;0 or 0&gt;|&lt;1 [ai]\w* 0&gt;|&lt;0 a\w* .&gt;|(&lt;[^P&lt;&gt;]*&gt;)
$#1

Try it online! Link includes test cases. Explanation: Works by considering each variable in turn, replacing the string f(p) with the string &lt;f(1) and f(0)&gt; for each variable p. The resulting string is then evaluated according to Boolean arithmetic.
{`

Repeat the entire program until the buffer stops changing.
T`()`&lt;&gt;

Change the ()s to something that doesn't need to be quoted.
.*P.*
&lt;$&amp; ¶ $&amp;&gt;

If the line still contains a variable, then duplicate it, and wrap the whole buffer in &lt;&gt;, however the two copies are still separated by a newline for now.
(?=(P'*))(?=.*\1[^P']*(¶|$))\1
$.2

Replace all copies of the last variable in the line with 1 or 0 depending on whether this is the original or duplicate line.
¶
a

Replace the newline with an a so that the two lines are joined together by an &lt; and &gt; operation.
&lt;not 1&gt;|&lt;0 or 0&gt;|&lt;1 [ai]\w* 0&gt;|&lt;0 a\w* .&gt;|(&lt;[^P&lt;&gt;]*&gt;)
$#1

Simplify any expressions that only contain constants. The expressions &lt;not 1&gt;, &lt;0 or 0&gt;, &lt;1 implies 0&gt;, &lt;1 and 0&gt;, &lt;0 and 0&gt;, &lt;0 and 1&gt; and &lt;0 and P&gt; (edge case) all evaluate to 0, while any other expression that contains no sub-expressions or variables evaluates to 1. (The original version of the code was buggy in this respect and needed a byte to fix it which I have included in the revised byte count in the header.)