Search code examples
phpparser-generatorpeg

How to add implicit multiplication to PHP PEG basic calculator grammar?


I have a problem with my PEG grammar in PHP that use php-peg (the project have more recent fork that is publish to packagist). My project is a fork of an expression parser that I want to replace with a generated parser that is way easier to modify.

Everything works well so far, but I have a problem adding implicit multiplication which is part of the original project features.

It looks like this:

8(5/2)

it should implicitly multiply 8 by the fraction.

My grammar so far has a lot of features, but I only want to know how to add implicit multiplication to a basic calculator example that looks like this:

Number: /[0-9]+/
Value: Number > | '(' > Expr > ')' >
    function Number( &$result, $sub ) {
        $result['val'] = $sub['text'] ;
    }
    function Expr( &$result, $sub ) {
        $result['val'] = $sub['val'] ;
    }

Times: '*' > operand:Value >
Div: '/' > operand:Value >
Product: Value > ( Times | Div ) *
    function Value( &$result, $sub ) {
        $result['val'] = $sub['val'] ;
    }
    function Times( &$result, $sub ) {
        $result['val'] *= $sub['operand']['val'] ;
    }
    function Div( &$result, $sub ) {
        $result['val'] /= $sub['operand']['val'] ;
    }

Plus: '+' > operand:Product >
Minus: '-' > operand:Product >
Sum: Product > ( Plus | Minus ) *
    function Product( &$result, $sub ) {
        $result['val'] = $sub['val'] ;
    }
    function Plus( &$result, $sub ) {
        $result['val'] += $sub['operand']['val'] ;
    }
    function Minus( &$result, $sub ) {
        $result['val'] -= $sub['operand']['val'] ;
    }

Expr: Sum
    function Sum( &$result, $sub ) {
        $result['val'] = $sub['val'] ;
    }

Located in project examples directory.

I've created basic calculator example project on GitHub.


Solution

  • I would try changing the Product rule to this:

    Times: '*' > operand:Value >
    ImplicitTimes: operand:Value >
    Div: '/' > operand:Value >
    Product: Value > ( Times | ImplicitTimes | Div ) *
        function Value( &$result, $sub ) {
            $result['val'] = $sub['val'] ;
        }
        function Times( &$result, $sub ) {
            $result['val'] *= $sub['operand']['val'] ;
        }
        function ImplicitTimes( &$result, $sub ) {
            $result['val'] *= $sub['operand']['val'] ;
        }
        function Div( &$result, $sub ) {
            $result['val'] /= $sub['operand']['val'] ;
        }