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();
}
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];
}
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);
}
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;
}
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);
}
Aggregations