tree-sitter/src/compiler/rules/pattern.cpp

132 lines
4 KiB
C++
Raw Normal View History

2013-12-18 20:58:05 -08:00
#include "rules.h"
using std::string;
2013-12-30 23:52:38 -08:00
using std::hash;
namespace tree_sitter {
namespace rules {
class PatternParser {
public:
PatternParser(const string &input) :
input(input),
position(0),
length(input.length()) {}
rule_ptr rule() {
auto result = term();
while (has_more_input() && peek() == '|') {
next();
result = choice({ result, term() });
}
return result;
}
private:
rule_ptr term() {
rule_ptr result = factor();
while (has_more_input() && (peek() != '|') && (peek() != ')'))
result = seq({ result, factor() });
return result;
}
rule_ptr factor() {
2013-11-15 13:35:35 -08:00
rule_ptr result = atom();
if (has_more_input() && (peek() == '+')) {
next();
result = repeat(result);
}
return result;
}
rule_ptr atom() {
rule_ptr result;
switch (peek()) {
case '(':
next();
result = rule();
2013-11-15 08:46:45 -08:00
if (peek() != ')')
error("mismatched parens");
else
next();
2013-11-15 08:46:45 -08:00
break;
case ')':
error("mismatched parens");
break;
case '\\':
next();
2013-11-20 19:00:20 -08:00
result = escaped_char(peek());
2013-11-15 08:46:45 -08:00
next();
break;
default:
result = character(peek());
next();
break;
}
2013-11-15 08:46:45 -08:00
return result;
}
2013-11-20 19:00:20 -08:00
rule_ptr escaped_char(char value) {
switch (value) {
case '(':
case ')':
return character(value);
case 'w':
return character(CharClassWord);
2013-11-20 19:00:20 -08:00
case 'd':
return character(CharClassDigit);
2013-11-20 19:00:20 -08:00
default:
error("unrecognized escape sequence");
return rule_ptr();
}
}
void next() {
position++;
}
char peek() {
return input[position];
}
bool has_more_input() {
return position < length;
}
2013-11-15 08:46:45 -08:00
void error(const char *message) {
throw string("Invalid regex pattern '") + input + "': " + message;
2013-11-15 08:46:45 -08:00
}
const string input;
const size_t length;
int position;
};
Pattern::Pattern(const string &string) : value(string) {};
2013-12-18 20:58:05 -08:00
bool Pattern::operator==(tree_sitter::rules::Rule const &other) const {
2013-11-20 19:00:20 -08:00
auto pattern = dynamic_cast<const Pattern *>(&other);
return pattern && (pattern->value == value);
}
2013-12-30 23:52:38 -08:00
size_t Pattern::hash_code() const {
return typeid(this).hash_code() ^ hash<string>()(value);
}
2014-01-02 13:04:41 -08:00
rule_ptr Pattern::copy() const {
return std::make_shared<Pattern>(*this);
}
string Pattern::to_string() const {
2013-12-30 23:12:19 -08:00
return string("#<pattern '") + value + "'>";
}
2013-12-18 20:58:05 -08:00
2013-12-19 23:16:13 -08:00
void Pattern::accept(Visitor &visitor) const {
2013-12-18 20:58:05 -08:00
visitor.visit(this);
}
rule_ptr Pattern::to_rule_tree() const {
return PatternParser(value).rule();
}
}
}