Parse arithmetic string with regular expression
<p>I need to parse an arithmetic string with only <em>times</em> (<code>*</code>) and <em>add</em> (<code>+</code>), e.g., <code>300+10*51+20+2*21</code>, use regular expressions. </p>

<p>I have the working code below: </p>

<pre><code>import re


input_str = '300+10*51+20+2*21'

#input_str = '1*2+3*4'


prod_re = re.compile(r"(\d+)\*(\d+)")
sum_re = re.compile(r"(\d+)\+?")

result = 0
index = 0
while (index &lt;= len(input_str)-1):
    #-----
    prod_match = prod_re.match(input_str, index)
    if prod_match:
        # print 'find prod', prod_match.groups()
        result += int(prod_match.group(1))*int(prod_match.group(2))
        index += len(prod_match.group(0))+1
        continue
    #-----
    sum_match = sum_re.match(input_str, index)
    if sum_match:
        # print 'find sum', sum_match.groups()
        result += int(sum_match.group(1))
        index += len(sum_match.group(0))
        continue
    #-----
    if (not prod_match) and (not sum_match):
        print 'None match, check input string'
        break


print result
</code></pre>

<p>I am wondering if there is a way to avoid creating the variable <code>index</code> above?    </p>

<p>The solution to your problem should be a possible sign preceded <code>term</code> followed by a list of terms, separated by an adding operator like in</p>

<pre><code>[+-]?({term}([+-]{term})*)
</code></pre>

<p>in which each term is one factor, followed by a possible empty list of a multiplicative operator and another factor, like this:</p>

<pre><code>{factor}([*/]{factor})*
</code></pre>

<p>where factor is a sequence of digits <code>[0-9]+</code>, so substituting, leads to:</p>

<pre><code>[+-]?([0-9]+([*/][0-9]+)*([+-][0-9]+([*/][0-9]+)*)*)
</code></pre>

<p>This will be a possible regexp that you can have, It assumes the structure of precedence between the operators that you can have.  But it doesn't allow you to extract the different elements, as is demonstrated easily:  the regexp has only 4 group elements inside (4 left parenthesis) so you can only match four of these (the first term, the last factor of the first term, the last term, and the last factor of the last term.  If you begin to surround subexpressions with parenthesis, you can get more, but thing that the number of groups in a regexp is <strong>finite</strong>, and you can construct a possible infinitely long regular expression.</p>

<p>Said this (that you will not be able to separate all groups of things from the regexp structure) a different approach is taken:  first sign is optional, and can be followed by an undefined number of terms, separated by either multiplicative operators or by additive ones:</p>

<pre><code>[+-]?([0-9]+([*/+-][0-9]+)*
</code></pre>

<p>will do the work also (it matches the same set of expressions.  Even if you restrict to the fact that only one operator can be interspesed in any secuence of 1 or more digits, the resulting regexp could be simplified to:</p>

<pre><code>[-+]?[0-9]([*/+-]?[0-9])*
</code></pre>

<p>or with the usual notations used nowadays, to:</p>

<pre><code>[-+]?\d([*/+-]?\d)* 
</code></pre>

python regex math