Pattern matching по значениям списка

This commit is contained in:
Victor 2016-06-25 19:36:07 +03:00
parent b957569759
commit 726e96488a
3 changed files with 146 additions and 22 deletions

View File

@ -38,3 +38,28 @@ def printArrayRecursive(arr) = match arr {
case []: "[]" case []: "[]"
case last: "[" + last + ", []]" case last: "[" + last + ", []]"
} }
println "\nPattern matching on arrays by value"
def tupleMatch(x) = match x {
case (0, 0): "00"
case (1, 0): "10"
case (0, 1): "01"
case (1, 1): "11"
case (2, _): "2?"
case _: "unknown"
}
println tupleMatch([0, 1])
println tupleMatch([1, 1])
println tupleMatch([2, 1])
println tupleMatch([3, 9])
println "\nFizzBuzz with pattern matching"
for i = 1, i <= 100, i++ {
println match [i % 3 == 0, i % 5 == 0] {
case (true, false): "Fizz"
case (false, true): "Buzz"
case (true, true): "FizzBuzz"
case _: i
}
}

View File

@ -368,6 +368,19 @@ public final class Parser {
match(TokenType.COLONCOLON); match(TokenType.COLONCOLON);
} }
pattern = listPattern; pattern = listPattern;
} else if (match(TokenType.LPAREN)) {
// case (1, 2):
final MatchExpression.TuplePattern tuplePattern = new MatchExpression.TuplePattern();
while (!match(TokenType.RPAREN)) {
if ("_".equals(get(0).getText())) {
tuplePattern.addAny();
consume(TokenType.WORD);
} else {
tuplePattern.add(expression());
}
match(TokenType.COMMA);
}
pattern = tuplePattern;
} }
if (pattern == null) { if (pattern == null) {

View File

@ -7,6 +7,7 @@ import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.Value; import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.lib.Variables; import com.annimon.ownlang.lib.Variables;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
/** /**
@ -49,7 +50,7 @@ public final class MatchExpression implements Expression, Statement {
} else { } else {
Variables.define(pattern.variable, value); Variables.define(pattern.variable, value);
if (optMatches(p)) { if (optMatches(p)) {
final Value result = evalResult(p.result);; final Value result = evalResult(p.result);
Variables.remove(pattern.variable); Variables.remove(pattern.variable);
return result; return result;
} }
@ -67,10 +68,29 @@ public final class MatchExpression implements Expression, Statement {
return result; return result;
} }
} }
if ((value.type() == Types.ARRAY) && (p instanceof TuplePattern)) {
final TuplePattern pattern = (TuplePattern) p;
if (matchTuplePattern((ArrayValue) value, pattern) && optMatches(p)) {
return evalResult(p.result);
}
}
} }
throw new PatternMatchingException("No pattern were matched"); throw new PatternMatchingException("No pattern were matched");
} }
private boolean matchTuplePattern(ArrayValue array, TuplePattern p) {
if (p.values.size() != array.size()) return false;
final int size = array.size();
for (int i = 0; i < size; i++) {
final Expression expr = p.values.get(i);
if ( (expr != TuplePattern.ANY) && (expr.eval().compareTo(array.get(i)) != 0) ) {
return false;
}
}
return true;
}
private boolean matchListPattern(ArrayValue array, ListPattern p) { private boolean matchListPattern(ArrayValue array, ListPattern p) {
final List<String> parts = p.parts; final List<String> parts = p.parts;
final int partsSize = parts.size(); final int partsSize = parts.size();
@ -232,7 +252,73 @@ public final class MatchExpression implements Expression, Statement {
@Override @Override
public String toString() { public String toString() {
return parts + ": " + result; final Iterator<String> it = parts.iterator();
if (it.hasNext()) {
final StringBuilder sb = new StringBuilder();
sb.append("[").append(it.next());
while (it.hasNext()) {
sb.append(" :: ").append(it.next());
}
sb.append("]: ").append(result);
return sb.toString();
}
return "[]: " + result;
} }
} }
public static class TuplePattern extends Pattern {
public List<Expression> values;
public TuplePattern() {
this(new ArrayList<Expression>());
}
public TuplePattern(List<Expression> parts) {
this.values = parts;
}
public void addAny() {
values.add(ANY);
}
public void add(Expression value) {
values.add(value);
}
@Override
public String toString() {
final Iterator<Expression> it = values.iterator();
if (it.hasNext()) {
final StringBuilder sb = new StringBuilder();
sb.append("(").append(it.next());
while (it.hasNext()) {
sb.append(", ").append(it.next());
}
sb.append("): ").append(result);
return sb.toString();
}
return "(): " + result;
}
private static final Expression ANY = new Expression() {
@Override
public Value eval() {
return NumberValue.ONE;
}
@Override
public void accept(Visitor visitor) {
}
@Override
public <R, T> R accept(ResultVisitor<R, T> visitor, T input) {
return null;
}
@Override
public String toString() {
return "_";
}
};
}
} }