Home > Blockchain >  regex to find if 2 variable are getting divide or multiplied
regex to find if 2 variable are getting divide or multiplied

Time:02-02

I am struggling with one expression

The basic requirement is 2 variables cannot be divided or multiplied. The expression gets complexed when we have to handle the BODMAS

Lets Say the Expression is

#f_1# this is equal to one variable

#f_1#/#f_2# (Valid) RegEx should Capture this expression

#f_1# 1000/#f_2# (Invalid) RegEx should not capture this

((#f_1#) 1000)/#f_2# (Valid) RegEx should capture this because according to BODMAS first brackets will be solved and the result is #f_1# 1000 and now expression is

#f_1# 1000/#f_2# which means fields are divided and we need to capture this pattern where 2 fields are getting divide and multiplied only

In the end

CodePudding user response:

I doubt regex can handle this. Even if you make it happen with a complex expression you would not be able to maintain it. To stay with simple, easy to understand code go for the recursive descent parser as already suggested.

https://www.antlr.org/ is definitely worth a look. In the documentation you may even get a definition how far you can go with regex, lexers and when to start looking at parsers.

CodePudding user response:

Regular expressions cannot do the nesting of arithmetic expressions with parentheses.

One solution is to consecutively apply redexes, reducible expressions.

Expression: ((#f_1#) 1000*20)/#f_2#
Reduced expression: @6
Expression tree: {@0=#f_1#, @1=#f_2#, @2=1000, @3=20, @4=@2*@3, @5=@0 @4, @6=@5/@1}

Expression nodes are represented as '@' number.

With (quite ugly written):

private void stackOverflow() {
    String expr = "((#f_1#) 1000*20)/#f_2#";
    System.out.println("Expression: "   expr);

    Map<String, String> vars = new HashMap<>();
    expr = reduceVars(expr, vars);
    expr = reduceNumbers(expr, vars);
    boolean changed;
    do {
        changed = false;
        String expr2 = reduceParentheses(expr, vars);
        if (!expr.equals(expr2)) {
            changed = true;
            expr = expr2;
            continue;
        }
        expr2 = reduceMultiplicative(expr, vars);
        if (!expr.equals(expr2)) {
            changed = true;
            expr = expr2;
            continue;
        }
        expr2 = reduceAdditive(expr, vars);
        if (!expr.equals(expr2)) {
            changed = true;
            expr = expr2;
        }
    } while (changed);

    System.out.println("Reduced expression: "   expr);
    System.out.println("Expression tree: "   vars);
}

The above enforces the BODMAS rule.

private String addVar(MatchResult mr,  Map<String, String> vars) {
    String v = "@"   vars.size();
    vars.put(v, mr.group());
    return v;
}

I use a simplified variable '@' number.

private String reduceVars(String expr, Map<String, String> vars) {
    return Pattern.compile("#\\w #").matcher(expr).replaceAll(mr -> addVar(mr, vars));
}

private String reduceNumbers(String expr, Map<String, String> vars) {
    return Pattern.compile("(?<!@)\\d ").matcher(expr).replaceAll(mr -> addVar(mr, vars));
}

private String reduceParentheses(String expr, Map<String, String> vars) {
    return Pattern.compile("\\((@\\d )\\)").matcher(expr).replaceAll(mr -> mr.group(1));
}

private String reduceMultiplicative(String expr, Map<String, String> vars) {
    return Pattern.compile("@\\d [/*]@\\d ").matcher(expr).replaceAll(mr -> addVar(mr, vars));
}

private String reduceAdditive(String expr, Map<String, String> vars) {
    return Pattern.compile("@\\d [- ]@\\d ").matcher(expr).replaceAll(mr -> addVar(mr, vars));
}

This is a simplification. You are actually building an expression tree, and you can do common sub-expression elimination, getting a directed acyclic graph i.o. a tree.

  •  Tags:  
  • Related