blob: 54cd9d9243e6df10bdd8090aff61bb7d414961a8 [file] [log] [blame]
swissChili7babd922021-12-02 22:46:48 -08001#include "Matcher.h"
2
swissChili3e98c062021-12-04 22:07:38 -08003#include <QDebug>
4
swissChilic71acc62021-12-07 08:03:37 -08005MatchResult match(QList<Token> data, QList<Token> pattern, VarContext context)
6{
7 if (data.empty() && pattern.empty())
8 {
swissChili7babd922021-12-02 22:46:48 -08009 return MatchResult{true, context};
10 }
11
swissChili07d325f2021-12-08 20:02:05 -080012 if ((pattern.empty() && !data.empty()) || (data.empty() && !pattern.empty()))
swissChili682e7bc2021-12-07 09:04:54 -080013 {
14 return MatchResult{false, context};
15 }
16
swissChili3e98c062021-12-04 22:07:38 -080017 Token ph = pattern.first();
swissChili7babd922021-12-02 22:46:48 -080018 Token dataHead = data.first();
19 pattern.removeFirst();
20
swissChili9dddbf72021-12-08 23:03:25 -080021 if (ph.isSym() || ph.isIdent() || ph.isInteger())
swissChilic71acc62021-12-07 08:03:37 -080022 {
23 if (ph == data.first())
24 {
swissChili7babd922021-12-02 22:46:48 -080025 data.removeFirst();
26 return match(data, pattern, context);
swissChilic71acc62021-12-07 08:03:37 -080027 }
28 else
29 {
swissChili7babd922021-12-02 22:46:48 -080030 return MatchResult{false, context};
31 }
swissChilic71acc62021-12-07 08:03:37 -080032 }
33 else if (ph.isParen())
34 {
swissChili7babd922021-12-02 22:46:48 -080035 data.removeFirst();
swissChilid17b5a12021-12-05 20:46:42 -080036
swissChili3e98c062021-12-04 22:07:38 -080037 auto result = match(dataHead.parenContent(), ph.parenContent(), context);
swissChili7babd922021-12-02 22:46:48 -080038
swissChilic71acc62021-12-07 08:03:37 -080039 if (result.success)
40 {
swissChili7babd922021-12-02 22:46:48 -080041 return match(data, pattern, result.context);
swissChilic71acc62021-12-07 08:03:37 -080042 }
43 else
44 {
swissChili7babd922021-12-02 22:46:48 -080045 return MatchResult{false, result.context};
46 }
swissChilic71acc62021-12-07 08:03:37 -080047 }
48 else if (ph.isVar())
49 {
swissChili3e98c062021-12-04 22:07:38 -080050 // is var bound?
swissChilic71acc62021-12-07 08:03:37 -080051 if (context.exists(ph.name()))
52 {
swissChili3e98c062021-12-04 22:07:38 -080053 // TODO: handle error elegantly if types don't match up (let's just assume the user isn't stupid)
54
swissChilic71acc62021-12-07 08:03:37 -080055 switch (ph.varType())
56 {
57 case 's':
58 case 't':
59 if (context.singleVar(ph.name()) == dataHead)
60 {
61 data.removeFirst();
62 return match(data, pattern, context);
63 }
64 else
65 {
66 return MatchResult{false, context};
67 }
68 case 'e':
69 QList<Token> expected = context.expressionVar(ph.name());
swissChili3e98c062021-12-04 22:07:38 -080070
swissChilic71acc62021-12-07 08:03:37 -080071 if (listStartsWith(data, expected))
72 {
73 listDrop(data, expected.length());
74 return match(data, pattern, context);
75 }
76 else
77 {
78 return MatchResult{false, context};
79 }
swissChili3e98c062021-12-04 22:07:38 -080080 }
swissChilic71acc62021-12-07 08:03:37 -080081 }
82 else
83 {
swissChili3e98c062021-12-04 22:07:38 -080084 bool typeIsOk = false;
85
swissChilic71acc62021-12-07 08:03:37 -080086 switch (ph.varType())
87 {
88 case 't':
89 if (dataHead.isParen())
90 typeIsOk = true;
swissChili3e98c062021-12-04 22:07:38 -080091
swissChilic71acc62021-12-07 08:03:37 -080092 case 's':
swissChili9dddbf72021-12-08 23:03:25 -080093 if (dataHead.isSym() || dataHead.isIdent() || dataHead.isInteger())
swissChilic71acc62021-12-07 08:03:37 -080094 typeIsOk = true;
swissChili3e98c062021-12-04 22:07:38 -080095
swissChilic71acc62021-12-07 08:03:37 -080096 if (!typeIsOk)
97 {
swissChili3e98c062021-12-04 22:07:38 -080098 return MatchResult{false, context};
swissChilic71acc62021-12-07 08:03:37 -080099 }
swissChilid17b5a12021-12-05 20:46:42 -0800100
swissChilic71acc62021-12-07 08:03:37 -0800101 context.add(ph.varType(), ph.name(), dataHead);
102 data.removeFirst();
103
104 return match(data, pattern, context);
105
106 case 'e':
swissChili923bd532021-12-08 22:48:58 -0800107 // Now this is tricky TODO: Optimize this to check if
108 // there is an obvious length that this expression has
109 // to be
110 for (int matchSyms = 0; matchSyms <= data.length(); matchSyms++)
swissChilic71acc62021-12-07 08:03:37 -0800111 {
112 QList<Token> slice = listSlice(data, 0, matchSyms);
113 VarContext newContext = context;
114 newContext.add(ph.varType(), ph.name(), slice);
115
swissChili923bd532021-12-08 22:48:58 -0800116 MatchResult tryMatch = match(
117 listSlice(data, matchSyms, data.length()),
118 pattern, newContext);
119
swissChilic71acc62021-12-07 08:03:37 -0800120 if (tryMatch.success)
121 {
122 return tryMatch;
123 }
swissChilic71acc62021-12-07 08:03:37 -0800124 }
125 // If this worked we would have returned already
126 return MatchResult{false, context};
127
128 default:
129 qDebug() << "#TYPE_ERROR";
130 return MatchResult{false, context};
swissChili3e98c062021-12-04 22:07:38 -0800131 }
132 }
swissChili7babd922021-12-02 22:46:48 -0800133 }
swissChili3e98c062021-12-04 22:07:38 -0800134
swissChili923bd532021-12-08 22:48:58 -0800135 qFatal("FALLING THROUGH, THIS SHOULD NOT HAPPEN");
swissChili3e98c062021-12-04 22:07:38 -0800136 // Fallthrough
137 return MatchResult{false, context};
swissChili7babd922021-12-02 22:46:48 -0800138}