| #include "Matcher.h" |
| |
| #include <QDebug> |
| |
| MatchResult match(QList<Token> data, QList<Token> pattern, VarContext context) { |
| if (data.empty() && pattern.empty()) { |
| return MatchResult{true, context}; |
| } |
| |
| Token ph = pattern.first(); |
| Token dataHead = data.first(); |
| pattern.removeFirst(); |
| |
| if (ph.isSym() || ph.isIdent()) { |
| if (ph == data.first()) { |
| data.removeFirst(); |
| return match(data, pattern, context); |
| } else { |
| return MatchResult{false, context}; |
| } |
| } else if (ph.isParen() && dataHead.isParen()) { |
| data.removeFirst(); |
| auto result = match(dataHead.parenContent(), ph.parenContent(), context); |
| |
| if (result.success) { |
| return match(data, pattern, result.context); |
| } else { |
| return MatchResult{false, result.context}; |
| } |
| } else if (ph.isVar()) { |
| // is var bound? |
| if (context.exists(ph.name())) { |
| // TODO: handle error elegantly if types don't match up (let's just assume the user isn't stupid) |
| |
| switch (ph.varType()) { |
| case 's': |
| case 't': |
| if (context.singleVar(ph.name()) == dataHead) { |
| data.removeFirst(); |
| return match(data, pattern, context); |
| } else { |
| return MatchResult{false, context}; |
| } |
| case 'e': |
| QList<Token> expected = context.expressionVar(ph.name()); |
| |
| if (listStartsWith(data, expected)) { |
| listDrop(data, expected.length()); |
| return match(data, pattern, context); |
| } else { |
| return MatchResult{false, context}; |
| } |
| } |
| } else { |
| bool typeIsOk = false; |
| |
| switch (ph.varType()) { |
| case 't': |
| if (dataHead.isParen()) |
| typeIsOk = true; |
| |
| case 's': |
| if (dataHead.isSym() || dataHead.isIdent()) |
| typeIsOk = true; |
| |
| if (!typeIsOk) { |
| return MatchResult{false, context}; |
| } |
| |
| context.add(ph.varType(), ph.name(), dataHead); |
| data.removeFirst(); |
| |
| return match(data, pattern, context); |
| |
| case 'e': |
| // Now this is tricky |
| for (int matchSyms = 1; matchSyms < data.length(); matchSyms++) { |
| QList<Token> slice = listSlice(data, 0, matchSyms); |
| VarContext newContext = context; |
| newContext.add(ph.varType(), ph.name(), slice); |
| |
| MatchResult tryMatch = match(listSlice(data, matchSyms, data.length()), pattern, newContext); |
| if (tryMatch.success) { |
| return tryMatch; |
| } |
| // else matchSyms ++ |
| } |
| // If this worked we would have returned already |
| return MatchResult{false, context}; |
| } |
| } |
| } |
| |
| qDebug() << "FALLING THROUGH, THIS SHOULD NOT HAPPEN"; |
| // Fallthrough |
| return MatchResult{false, context}; |
| } |