Search in sources :

Example 1 with PatternNested

use of org.matheclipse.core.expression.PatternNested in project symja_android_library by axkr.

the class IPatternMap method determinePatterns.

/**
 * Determine all patterns (i.e. all objects of instance IPattern) in the given expression
 *
 * <p>
 * Increments this classes pattern counter.
 *
 * @param lhsPatternExpr the (left-hand-side) expression which could contain pattern objects.
 * @return the priority of this pattern-matcher
 */
static IPatternMap determinePatterns(final IExpr lhsPatternExpr, int[] priority, PatternNested p2) {
    if (lhsPatternExpr instanceof IAST) {
        List<Pair<IExpr, IPatternObject>> patternIndexMap = new ArrayList<Pair<IExpr, IPatternObject>>();
        boolean[] ruleWithoutPattern = new boolean[] { true };
        if (p2 != null) {
            ruleWithoutPattern[0] = false;
            int[] result = p2.addPattern(patternIndexMap);
            priority[0] -= result[1];
        }
        determinePatternsRecursive(patternIndexMap, (IAST) lhsPatternExpr, priority, ruleWithoutPattern, 1);
        int size = patternIndexMap.size();
        switch(size) {
            case 1:
                PatternMap1 patternMap1 = new PatternMap1();
                patternMap1.fSymbol1 = patternIndexMap.get(0).getFirst();
                patternMap1.fPatternObject1 = patternIndexMap.get(0).getSecond();
                return patternMap1;
            case 2:
                PatternMap2 patternMap2 = new PatternMap2();
                patternMap2.fSymbol1 = patternIndexMap.get(0).getFirst();
                patternMap2.fPatternObject1 = patternIndexMap.get(0).getSecond();
                patternMap2.fSymbol2 = patternIndexMap.get(1).getFirst();
                patternMap2.fPatternObject2 = patternIndexMap.get(1).getSecond();
                return patternMap2;
            case 3:
                PatternMap3 patternMap3 = new PatternMap3();
                patternMap3.fSymbol1 = patternIndexMap.get(0).getFirst();
                patternMap3.fPatternObject1 = patternIndexMap.get(0).getSecond();
                patternMap3.fSymbol2 = patternIndexMap.get(1).getFirst();
                patternMap3.fPatternObject2 = patternIndexMap.get(1).getSecond();
                patternMap3.fSymbol3 = patternIndexMap.get(2).getFirst();
                patternMap3.fPatternObject3 = patternIndexMap.get(2).getSecond();
                return patternMap3;
        }
        PatternMap patternMap = new PatternMap();
        patternMap.fRuleWithoutPattern = ruleWithoutPattern[0];
        patternMap.fSymbolsOrPattern = new IExpr[size];
        patternMap.fSymbolsOrPatternValues = new IExpr[size];
        patternMap.fPatternObjects = new IPatternObject[size];
        int i = 0;
        for (Pair<IExpr, IPatternObject> entry : patternIndexMap) {
            patternMap.fSymbolsOrPattern[i] = entry.getFirst();
            patternMap.fPatternObjects[i] = entry.getSecond();
            i++;
        }
        return patternMap;
    } else if (lhsPatternExpr instanceof PatternNested) {
        PatternNested pattern2 = (PatternNested) lhsPatternExpr;
        // patternMap1.fPatternObject1 = pattern;
        return determinePatterns(pattern2.getPatternExpr(), priority, pattern2);
    } else if (lhsPatternExpr instanceof IPatternObject) {
        if (p2 != null) {
            PatternMap2 patternMap2 = new PatternMap2();
            patternMap2.fSymbol1 = p2.getSymbol();
            patternMap2.fPatternObject1 = p2;
            IPatternObject pattern = (IPatternObject) lhsPatternExpr;
            final ISymbol sym = pattern.getSymbol();
            patternMap2.fSymbol2 = (sym != null) ? sym : pattern;
            patternMap2.fPatternObject2 = pattern;
            return patternMap2;
        }
        PatternMap1 patternMap1 = new PatternMap1();
        IPatternObject pattern = (IPatternObject) lhsPatternExpr;
        final ISymbol sym = pattern.getSymbol();
        patternMap1.fSymbol1 = (sym != null) ? sym : pattern;
        patternMap1.fPatternObject1 = pattern;
        return patternMap1;
    }
    return new PatternMap0();
}
Also used : ISymbol(org.matheclipse.core.interfaces.ISymbol) IPatternObject(org.matheclipse.core.interfaces.IPatternObject) ArrayList(java.util.ArrayList) IAST(org.matheclipse.core.interfaces.IAST) IExpr(org.matheclipse.core.interfaces.IExpr) PatternNested(org.matheclipse.core.expression.PatternNested) Pair(org.hipparchus.util.Pair)

Example 2 with PatternNested

use of org.matheclipse.core.expression.PatternNested in project symja_android_library by axkr.

the class IPatternMap method determinePatternsRecursive.

/**
 * Determine all patterns (i.e. all objects of instance IPattern) in the given expression
 *
 * <p>
 * Increments this classes pattern counter.
 *
 * @param patternIndexMap
 * @param lhsPatternExpr the (left-hand-side) expression which could contain pattern objects.
 * @param treeLevel the level of the tree where the patterns are determined
 */
static int determinePatternsRecursive(List<Pair<IExpr, IPatternObject>> patternIndexMap, final IAST lhsPatternExpr, int[] priority, boolean[] ruleWithoutPattern, int treeLevel) {
    int[] listEvalFlags = new int[] { IAST.NO_FLAG };
    if (lhsPatternExpr.isAlternatives() || lhsPatternExpr.isExcept()) {
        ruleWithoutPattern[0] = false;
    }
    lhsPatternExpr.forEach(x -> {
        if (x.isASTOrAssociation()) {
            final IAST lhsPatternAST = (IAST) x;
            if (lhsPatternAST.isPatternMatchingFunction()) {
                listEvalFlags[0] |= IAST.CONTAINS_PATTERN;
            }
            listEvalFlags[0] |= determinePatternsRecursive(patternIndexMap, lhsPatternAST, priority, ruleWithoutPattern, treeLevel + 1);
            priority[0] -= 11;
            if (x.isPatternDefault()) {
                listEvalFlags[0] |= IAST.CONTAINS_DEFAULT_PATTERN;
            }
        } else if (x instanceof IPatternObject) {
            ruleWithoutPattern[0] = false;
            int[] result = ((IPatternObject) x).addPattern(patternIndexMap);
            listEvalFlags[0] |= result[0];
            priority[0] -= result[1];
            if (x instanceof PatternNested) {
                IExpr patternExpr = ((PatternNested) x).getPatternExpr();
                if (patternExpr.isASTOrAssociation()) {
                    listEvalFlags[0] |= determinePatternsRecursive(patternIndexMap, (IAST) patternExpr, priority, ruleWithoutPattern, treeLevel + 1);
                    priority[0] -= 11;
                    if (x.isPatternDefault()) {
                        listEvalFlags[0] |= IAST.CONTAINS_DEFAULT_PATTERN;
                    }
                }
            }
        } else {
            priority[0] -= (50 - treeLevel);
        }
    }, 0);
    lhsPatternExpr.setEvalFlags(listEvalFlags[0]);
    // listEvalFlags &= IAST.CONTAINS_NO_DEFAULT_PATTERN_MASK;
    return listEvalFlags[0];
}
Also used : IPatternObject(org.matheclipse.core.interfaces.IPatternObject) IAST(org.matheclipse.core.interfaces.IAST) PatternNested(org.matheclipse.core.expression.PatternNested) IExpr(org.matheclipse.core.interfaces.IExpr)

Example 3 with PatternNested

use of org.matheclipse.core.expression.PatternNested in project symja_android_library by axkr.

the class PatternMatcher method matchPattern.

private boolean matchPattern(IPatternObject lhsPatternExpr, final IExpr lhsEvalExpr, EvalEngine engine, StackMatcher stackMatcher) {
    if (lhsPatternExpr instanceof PatternNested) {
        PatternNested pattern2 = (PatternNested) lhsPatternExpr;
        IExpr patternExpr = pattern2.getPatternExpr();
        if (matchExpr(patternExpr, lhsEvalExpr, engine, stackMatcher)) {
            return pattern2.matchPattern(lhsEvalExpr, fPatternMap);
        }
        return false;
    }
    return lhsPatternExpr.matchPattern(lhsEvalExpr, fPatternMap);
}
Also used : PatternNested(org.matheclipse.core.expression.PatternNested) IExpr(org.matheclipse.core.interfaces.IExpr)

Example 4 with PatternNested

use of org.matheclipse.core.expression.PatternNested in project symja_android_library by axkr.

the class StringFunctions method toRegexString.

/**
 * Convert a Symja expression which represents a 'piece of a regular expression' to a Java regular
 * expression string.
 *
 * @param partOfRegex the expression which represents a regex 'piece' which must be converted to a
 *        Java regex string
 * @param abbreviatedPatterns if <code>true</code> allow 'abbreviated patterns" in strings (i.e.
 *        '\','*' and '@' operators)
 * @param stringFunction the original string function, used in error messages
 * @param shortestLongest either {@link #REGEX_LONGEST} or {@link #REGEX_SHORTEST}
 * @param groups
 * @param engine the evaluation engine
 * @return
 * @see <a href="https://en.wikipedia.org/wiki/Perl_Compatible_Regular_Expressions">Wikipedia -
 *      Perl Compatible Regular Expression</a>
 */
private static String toRegexString(IExpr partOfRegex, boolean abbreviatedPatterns, IAST stringFunction, String[] shortestLongest, Map<ISymbol, String> groups, EvalEngine engine) {
    if (partOfRegex.isString()) {
        final String str = partOfRegex.toString();
        if (abbreviatedPatterns) {
            StringBuilder pieces = new StringBuilder();
            int beginIndex = 0;
            int endIndex = 0;
            final int len = str.length();
            while (endIndex < len) {
                char c = str.charAt(endIndex);
                if (c == '\\' && endIndex + 1 < len) {
                    pieces.append(Pattern.quote(str.substring(beginIndex, endIndex)));
                    pieces.append(Pattern.quote(str.substring(endIndex + 1, endIndex + 2)));
                    endIndex += 2;
                    beginIndex = endIndex;
                } else if (c == '*') {
                    pieces.append(Pattern.quote(str.substring(beginIndex, endIndex)));
                    pieces.append("(.*)");
                    endIndex += 1;
                    beginIndex = endIndex;
                } else if (c == '@') {
                    pieces.append(Pattern.quote(str.substring(beginIndex, endIndex)));
                    // one or more characters, excluding upper case letters
                    pieces.append("([^A-Z]+)");
                    endIndex += 1;
                    beginIndex = endIndex;
                } else {
                    endIndex += 1;
                }
            }
            pieces.append(Pattern.quote(str.substring(beginIndex, endIndex)));
            return pieces.toString();
        } else {
            return Pattern.quote(str);
        }
    } else if (partOfRegex.isAST(S.Characters, 2) && partOfRegex.first().isString()) {
        String str = ((IStringX) partOfRegex.first()).toString();
        return "[" + str + "]";
    } else if (partOfRegex.isAST(S.RegularExpression, 2) && partOfRegex.first().isString()) {
        return ((IStringX) partOfRegex.first()).toString();
    } else if (partOfRegex instanceof RepeatedPattern) {
        RepeatedPattern repeated = (RepeatedPattern) partOfRegex;
        IExpr expr = repeated.getRepeatedExpr();
        if (expr == null) {
            return null;
        }
        if (expr.isAST(S.Pattern, 3) && expr.first().isSymbol()) {
            final ISymbol symbol = (ISymbol) expr.first();
            String str = toRegexString(expr.second(), abbreviatedPatterns, stringFunction, shortestLongest, groups, engine);
            if (str != null) {
                final String groupName = symbol.toString();
                groups.put(symbol, groupName);
                if (repeated.isNullSequence()) {
                    return "(?<" + groupName + ">(" + str + ")" + shortestLongest[ASTERISK_Q] + ")";
                } else {
                    return "(?<" + groupName + ">(" + str + ")" + shortestLongest[PLUS_Q] + ")";
                }
            }
        } else {
            String str = toRegexString(expr, abbreviatedPatterns, stringFunction, shortestLongest, groups, engine);
            if (str != null) {
                if (repeated.isNullSequence()) {
                    return "(" + str + ")" + shortestLongest[ASTERISK_Q];
                } else {
                    return "(" + str + ")" + shortestLongest[PLUS_Q];
                }
            }
        }
    } else if (partOfRegex.isAST(S.StringExpression)) {
        IAST stringExpression = (IAST) partOfRegex;
        return toRegexString(stringFunction, stringExpression, abbreviatedPatterns, shortestLongest, groups, engine);
    } else if (partOfRegex.isBlank()) {
        return "(.|\\n)";
    } else if (partOfRegex.isPattern()) {
        final IPattern pattern = (IPattern) partOfRegex;
        final ISymbol symbol = pattern.getSymbol();
        if (symbol != null && pattern.getHeadTest() == null) {
            // see github #221 - use Java regex - named capturing groups
            final String groupName = symbol.toString();
            groups.put(symbol, groupName);
            if (pattern instanceof PatternNested) {
                PatternNested pn = (PatternNested) pattern;
                IExpr subPattern = pn.getPatternExpr();
                String subPatternRegex = toRegexString(subPattern, abbreviatedPatterns, stringFunction, shortestLongest, groups, engine);
                return "(?<" + groupName + ">" + subPatternRegex + ")";
            }
            return "(?<" + groupName + ">(.|\\n))";
        }
    } else if (partOfRegex.isAST(S.Pattern, 3) && partOfRegex.first().isSymbol()) {
        final ISymbol symbol = (ISymbol) partOfRegex.first();
        String str = toRegexString(partOfRegex.second(), abbreviatedPatterns, stringFunction, shortestLongest, groups, engine);
        if (str != null) {
            final String groupName = symbol.toString();
            groups.put(symbol, groupName);
            return "(?<" + groupName + ">" + str + ")";
        }
    } else if (partOfRegex.isPatternSequence(false)) {
        PatternSequence ps = ((PatternSequence) partOfRegex);
        final ISymbol symbol = ps.getSymbol();
        final String str;
        if (ps.isNullSequence()) {
            // RepeatedNull
            str = "(.|\\n)" + shortestLongest[ASTERISK_Q];
        } else {
            // Repeated
            str = "(.|\\n)" + shortestLongest[PLUS_Q];
        }
        if (symbol == null) {
            return str;
        } else {
            final String groupName = symbol.toString();
            groups.put(symbol, groupName);
            return "(?<" + groupName + ">" + str + ")";
        }
    } else if (partOfRegex.isAST(S.CharacterRange, 3)) {
        String[] characterRange = characterRange((IAST) partOfRegex);
        if (characterRange != null) {
            StringBuilder buf = new StringBuilder();
            buf.append("[");
            buf.append(Pattern.quote(characterRange[0]));
            buf.append("-");
            buf.append(Pattern.quote(characterRange[1]));
            buf.append("]");
            return buf.toString();
        }
    } else if (partOfRegex.isAlternatives()) {
        IAST alternatives = (IAST) partOfRegex;
        StringBuilder pieces = new StringBuilder();
        for (int i = 1; i < alternatives.size(); i++) {
            String str = toRegexString(alternatives.get(i), abbreviatedPatterns, stringFunction, shortestLongest, groups, engine);
            if (str == null) {
                // `1` currently not supported in `2`.
                IOFunctions.printMessage(stringFunction.topHead(), "unsupported", F.list(alternatives.get(i), stringFunction.topHead()), engine);
                return null;
            }
            pieces.append(str);
            if (i < alternatives.size() - 1) {
                pieces.append('|');
            }
        }
        return pieces.toString();
    } else if (partOfRegex.isAST(S.Shortest, 2)) {
        String str = toRegexString(partOfRegex.first(), abbreviatedPatterns, stringFunction, REGEX_SHORTEST, groups, engine);
        return str;
    } else if (partOfRegex.isAST(S.Longest, 2)) {
        return toRegexString(partOfRegex.first(), abbreviatedPatterns, stringFunction, REGEX_LONGEST, groups, engine);
    } else if (partOfRegex.isBuiltInSymbol()) {
        int ordinal = ((IBuiltInSymbol) partOfRegex).ordinal();
        switch(ordinal) {
            case ID.NumberString:
                // better suitable for StringSplit?
                return "[0-9]{1,13}(\\.[0-9]+)?";
            // return "[-|+]?(\\d+(\\.\\d*)?|\\.\\d+)?";
            case ID.Whitespace:
                return "(?u)\\s+";
            case ID.DigitCharacter:
                return "\\d";
            case ID.WhitespaceCharacter:
                return "(?u)\\s";
            case ID.WordCharacter:
                return "(?u)[^\\W_]";
            case ID.StartOfLine:
                return "\\R";
            case ID.EndOfLine:
                return "$";
            case ID.StartOfString:
                return "\\A";
            case ID.EndOfString:
                return "\\Z";
            case ID.WordBoundary:
                return "\\b";
            case ID.LetterCharacter:
                return "(?u)[^\\W_0-9]";
            case ID.HexidecimalCharacter:
                return "[0-9a-fA-F]";
            default:
                // `1` currently not supported in `2`.
                IOFunctions.printMessage(stringFunction.topHead(), "unsupported", F.list(partOfRegex, stringFunction.topHead()), engine);
                return null;
        }
    }
    // `1` currently not supported in `2`.
    IOFunctions.printMessage(stringFunction.topHead(), "unsupported", F.list(partOfRegex, stringFunction.topHead()), engine);
    return null;
}
Also used : IPattern(org.matheclipse.core.interfaces.IPattern) RepeatedPattern(org.matheclipse.core.expression.RepeatedPattern) ISymbol(org.matheclipse.core.interfaces.ISymbol) PatternSequence(org.matheclipse.core.expression.PatternSequence) IStringX(org.matheclipse.core.interfaces.IStringX) IExpr(org.matheclipse.core.interfaces.IExpr) IAST(org.matheclipse.core.interfaces.IAST) PatternNested(org.matheclipse.core.expression.PatternNested)

Example 5 with PatternNested

use of org.matheclipse.core.expression.PatternNested in project symja_android_library by axkr.

the class PatternMatching method setDelayedDownRule.

private static void setDelayedDownRule(IExpr leftHandSide, int flags, IExpr rightHandSide, boolean packageMode) {
    ISymbol lhsSymbol = null;
    if (leftHandSide instanceof PatternNested) {
        PatternNested pn = (PatternNested) leftHandSide;
        IExpr pattern = pn.getPatternExpr();
        lhsSymbol = determineRuleTag(pattern);
    }
    if (leftHandSide.isAST()) {
        lhsSymbol = determineRuleTag(leftHandSide);
    }
    if (lhsSymbol != null) {
        if (lhsSymbol.isProtected()) {
            // Symbol `1` is Protected.
            IOFunctions.printMessage(S.SetDelayed, "wrsym", F.list(lhsSymbol), EvalEngine.get());
            throw new FailedException();
        }
        lhsSymbol.putDownRule(flags | IPatternMatcher.SET_DELAYED, false, leftHandSide, rightHandSide, packageMode);
        return;
    }
    if (leftHandSide.isSymbol()) {
        lhsSymbol = (ISymbol) leftHandSide;
        if (lhsSymbol.isProtected()) {
            // Symbol `1` is Protected.
            IOFunctions.printMessage(S.SetDelayed, "wrsym", F.list(lhsSymbol), EvalEngine.get());
            throw new FailedException();
        }
        ((ISymbol) leftHandSide).assignValue(rightHandSide, true);
        return;
    }
    throw new RuleCreationError(leftHandSide);
}
Also used : ISymbol(org.matheclipse.core.interfaces.ISymbol) FailedException(org.matheclipse.core.eval.exception.FailedException) PatternNested(org.matheclipse.core.expression.PatternNested) IExpr(org.matheclipse.core.interfaces.IExpr) RuleCreationError(org.matheclipse.core.eval.exception.RuleCreationError)

Aggregations

PatternNested (org.matheclipse.core.expression.PatternNested)5 IExpr (org.matheclipse.core.interfaces.IExpr)5 IAST (org.matheclipse.core.interfaces.IAST)3 ISymbol (org.matheclipse.core.interfaces.ISymbol)3 IPatternObject (org.matheclipse.core.interfaces.IPatternObject)2 ArrayList (java.util.ArrayList)1 Pair (org.hipparchus.util.Pair)1 FailedException (org.matheclipse.core.eval.exception.FailedException)1 RuleCreationError (org.matheclipse.core.eval.exception.RuleCreationError)1 PatternSequence (org.matheclipse.core.expression.PatternSequence)1 RepeatedPattern (org.matheclipse.core.expression.RepeatedPattern)1 IPattern (org.matheclipse.core.interfaces.IPattern)1 IStringX (org.matheclipse.core.interfaces.IStringX)1