123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- /*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "src/sksl/lex/RegexParser.h"
- #include "src/sksl/lex/LexUtil.h"
- RegexNode RegexParser::parse(std::string source) {
- fSource = source;
- fIndex = 0;
- SkASSERT(fStack.size() == 0);
- this->regex();
- SkASSERT(fStack.size() == 1);
- SkASSERT(fIndex == source.size());
- return this->pop();
- }
- char RegexParser::peek() {
- if (fIndex >= fSource.size()) {
- return END;
- }
- return fSource[fIndex];
- }
- void RegexParser::expect(char c) {
- if (this->peek() != c) {
- printf("expected '%c' at index %d, but found '%c'", c, (int) fIndex, this->peek());
- exit(1);
- }
- ++fIndex;
- }
- RegexNode RegexParser::pop() {
- RegexNode result = fStack.top();
- fStack.pop();
- return result;
- }
- void RegexParser::term() {
- switch (this->peek()) {
- case '(': this->group(); break;
- case '[': this->set(); break;
- case '.': this->dot(); break;
- default: this->literal();
- }
- }
- void RegexParser::quantifiedTerm() {
- this->term();
- switch (this->peek()) {
- case '*': fStack.push(RegexNode(RegexNode::kStar_Kind, this->pop())); ++fIndex; break;
- case '+': fStack.push(RegexNode(RegexNode::kPlus_Kind, this->pop())); ++fIndex; break;
- case '?': fStack.push(RegexNode(RegexNode::kQuestion_Kind, this->pop())); ++fIndex; break;
- default: break;
- }
- }
- void RegexParser::sequence() {
- this->quantifiedTerm();
- for (;;) {
- switch (this->peek()) {
- case END: // fall through
- case '|': // fall through
- case ')': return;
- default:
- this->sequence();
- RegexNode right = this->pop();
- RegexNode left = this->pop();
- fStack.emplace(RegexNode::kConcat_Kind, std::move(left), std::move(right));
- }
- }
- }
- RegexNode RegexParser::escapeSequence(char c) {
- switch (c) {
- case 'n': return RegexNode(RegexNode::kChar_Kind, '\n');
- case 'r': return RegexNode(RegexNode::kChar_Kind, '\r');
- case 't': return RegexNode(RegexNode::kChar_Kind, '\t');
- case 's': return RegexNode(RegexNode::kCharset_Kind, " \t\n\r");
- default: return RegexNode(RegexNode::kChar_Kind, c);
- }
- }
- void RegexParser::literal() {
- char c = this->peek();
- if (c == '\\') {
- ++fIndex;
- fStack.push(this->escapeSequence(peek()));
- ++fIndex;
- }
- else {
- fStack.push(RegexNode(RegexNode::kChar_Kind, c));
- ++fIndex;
- }
- }
- void RegexParser::dot() {
- this->expect('.');
- fStack.push(RegexNode(RegexNode::kDot_Kind));
- }
- void RegexParser::group() {
- this->expect('(');
- this->regex();
- this->expect(')');
- }
- void RegexParser::setItem() {
- this->literal();
- if (this->peek() == '-') {
- ++fIndex;
- if (peek() == ']') {
- fStack.push(RegexNode(RegexNode::kChar_Kind, '-'));
- }
- else {
- literal();
- RegexNode end = this->pop();
- SkASSERT(end.fKind == RegexNode::kChar_Kind);
- RegexNode start = this->pop();
- SkASSERT(start.fKind == RegexNode::kChar_Kind);
- fStack.push(RegexNode(RegexNode::kRange_Kind, std::move(start), std::move(end)));
- }
- }
- }
- void RegexParser::set() {
- expect('[');
- size_t depth = fStack.size();
- RegexNode set(RegexNode::kCharset_Kind);
- if (this->peek() == '^') {
- ++fIndex;
- set.fPayload.fBool = true;
- }
- else {
- set.fPayload.fBool = false;
- }
- for (;;) {
- switch (this->peek()) {
- case ']':
- ++fIndex;
- while (fStack.size() > depth) {
- set.fChildren.push_back(this->pop());
- }
- fStack.push(std::move(set));
- return;
- case END:
- printf("unterminated character set\n");
- exit(1);
- default:
- this->setItem();
- }
- }
- }
- void RegexParser::regex() {
- this->sequence();
- switch (this->peek()) {
- case '|': {
- ++fIndex;
- this->regex();
- RegexNode right = this->pop();
- RegexNode left = this->pop();
- fStack.push(RegexNode(RegexNode::kOr_Kind, left, right));
- break;
- }
- case END: // fall through
- case ')':
- return;
- default:
- SkASSERT(false);
- }
- }
|