2 * Copyright 2017 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "src/sksl/lex/RegexParser.h"
10 #include "src/sksl/lex/LexUtil.h"
17 RegexNode RegexParser::parse(std::string source) {
20 SkASSERT(fStack.size() == 0);
22 SkASSERT(fStack.size() == 1);
23 SkASSERT(fIndex == source.size());
27 char RegexParser::peek() {
28 if (fIndex >= fSource.size()) {
31 return fSource[fIndex];
34 void RegexParser::expect(char c) {
35 if (this->peek() != c) {
36 printf("expected '%c' at index %d, but found '%c'", c, (int) fIndex, this->peek());
42 RegexNode RegexParser::pop() {
43 RegexNode result = fStack.top();
48 void RegexParser::term() {
49 switch (this->peek()) {
50 case '(': this->group(); break;
51 case '[': this->set(); break;
52 case '.': this->dot(); break;
53 default: this->literal(); break;
57 void RegexParser::quantifiedTerm() {
59 switch (this->peek()) {
60 case '*': fStack.push(RegexNode(RegexNode::kStar_Kind, this->pop())); ++fIndex; break;
61 case '+': fStack.push(RegexNode(RegexNode::kPlus_Kind, this->pop())); ++fIndex; break;
62 case '?': fStack.push(RegexNode(RegexNode::kQuestion_Kind, this->pop())); ++fIndex; break;
67 void RegexParser::sequence() {
68 this->quantifiedTerm();
70 switch (this->peek()) {
71 case END: [[fallthrough]];
72 case '|': [[fallthrough]];
76 RegexNode right = this->pop();
77 RegexNode left = this->pop();
78 fStack.emplace(RegexNode::kConcat_Kind, std::move(left), std::move(right));
84 RegexNode RegexParser::escapeSequence(char c) {
86 case 'n': return RegexNode(RegexNode::kChar_Kind, '\n');
87 case 'r': return RegexNode(RegexNode::kChar_Kind, '\r');
88 case 't': return RegexNode(RegexNode::kChar_Kind, '\t');
89 case 's': return RegexNode(RegexNode::kCharset_Kind, " \t\n\r");
90 default: return RegexNode(RegexNode::kChar_Kind, c);
94 void RegexParser::literal() {
95 char c = this->peek();
98 fStack.push(this->escapeSequence(peek()));
102 fStack.push(RegexNode(RegexNode::kChar_Kind, c));
107 void RegexParser::dot() {
109 fStack.push(RegexNode(RegexNode::kDot_Kind));
112 void RegexParser::group() {
118 void RegexParser::setItem() {
120 if (this->peek() == '-') {
123 fStack.push(RegexNode(RegexNode::kChar_Kind, '-'));
127 RegexNode end = this->pop();
128 SkASSERT(end.fKind == RegexNode::kChar_Kind);
129 RegexNode start = this->pop();
130 SkASSERT(start.fKind == RegexNode::kChar_Kind);
131 fStack.push(RegexNode(RegexNode::kRange_Kind, std::move(start), std::move(end)));
136 void RegexParser::set() {
138 size_t depth = fStack.size();
139 RegexNode set(RegexNode::kCharset_Kind);
140 if (this->peek() == '^') {
142 set.fPayload.fBool = true;
145 set.fPayload.fBool = false;
148 switch (this->peek()) {
151 while (fStack.size() > depth) {
152 set.fChildren.push_back(this->pop());
154 fStack.push(std::move(set));
157 printf("unterminated character set\n");
166 void RegexParser::regex() {
168 switch (this->peek()) {
172 RegexNode right = this->pop();
173 RegexNode left = this->pop();
174 fStack.push(RegexNode(RegexNode::kOr_Kind, left, right));
177 case END: // fall through