Blame src/lexer.hpp

Packit Service 7770af
#ifndef SASS_LEXER_H
Packit Service 7770af
#define SASS_LEXER_H
Packit Service 7770af
Packit Service 7770af
#include <cstring>
Packit Service 7770af
Packit Service 7770af
namespace Sass {
Packit Service 7770af
  namespace Prelexer {
Packit Service 7770af
Packit Service 7770af
    //####################################
Packit Service 7770af
    // BASIC CHARACTER MATCHERS
Packit Service 7770af
    //####################################
Packit Service 7770af
Packit Service 7770af
    // Match standard control chars
Packit Service 7770af
    const char* kwd_at(const char* src);
Packit Service 7770af
    const char* kwd_dot(const char* src);
Packit Service 7770af
    const char* kwd_comma(const char* src);
Packit Service 7770af
    const char* kwd_colon(const char* src);
Packit Service 7770af
    const char* kwd_star(const char* src);
Packit Service 7770af
    const char* kwd_plus(const char* src);
Packit Service 7770af
    const char* kwd_minus(const char* src);
Packit Service 7770af
    const char* kwd_slash(const char* src);
Packit Service 7770af
Packit Service 7770af
    //####################################
Packit Service 7770af
    // BASIC CLASS MATCHERS
Packit Service 7770af
    //####################################
Packit Service 7770af
Packit Service 7770af
    // These are locale independant
Packit Service 7770af
    bool is_space(const char& src);
Packit Service 7770af
    bool is_alpha(const char& src);
Packit Service 7770af
    bool is_punct(const char& src);
Packit Service 7770af
    bool is_digit(const char& src);
Packit Service 7770af
    bool is_alnum(const char& src);
Packit Service 7770af
    bool is_xdigit(const char& src);
Packit Service 7770af
    bool is_unicode(const char& src);
Packit Service 7770af
    bool is_nonascii(const char& src);
Packit Service 7770af
    bool is_character(const char& src);
Packit Service 7770af
    bool is_uri_character(const char& src);
Packit Service 7770af
    bool escapable_character(const char& src);
Packit Service 7770af
Packit Service 7770af
    // Match a single ctype predicate.
Packit Service 7770af
    const char* space(const char* src);
Packit Service 7770af
    const char* alpha(const char* src);
Packit Service 7770af
    const char* digit(const char* src);
Packit Service 7770af
    const char* xdigit(const char* src);
Packit Service 7770af
    const char* alnum(const char* src);
Packit Service 7770af
    const char* punct(const char* src);
Packit Service 7770af
    const char* hyphen(const char* src);
Packit Service 7770af
    const char* unicode(const char* src);
Packit Service 7770af
    const char* nonascii(const char* src);
Packit Service 7770af
    const char* character(const char* src);
Packit Service 7770af
    const char* uri_character(const char* src);
Packit Service 7770af
    const char* escapable_character(const char* src);
Packit Service 7770af
Packit Service 7770af
    // Match multiple ctype characters.
Packit Service 7770af
    const char* spaces(const char* src);
Packit Service 7770af
    const char* digits(const char* src);
Packit Service 7770af
    const char* hyphens(const char* src);
Packit Service 7770af
Packit Service 7770af
    // Whitespace handling.
Packit Service 7770af
    const char* no_spaces(const char* src);
Packit Service 7770af
    const char* optional_spaces(const char* src);
Packit Service 7770af
Packit Service 7770af
    // Match any single character (/./).
Packit Service 7770af
    const char* any_char(const char* src);
Packit Service 7770af
Packit Service 7770af
    // Assert word boundary (/\b/)
Packit Service 7770af
    // Is a zero-width positive lookaheads
Packit Service 7770af
    const char* word_boundary(const char* src);
Packit Service 7770af
Packit Service 7770af
    // Match a single linebreak (/(?:\n|\r\n?)/).
Packit Service 7770af
    const char* re_linebreak(const char* src);
Packit Service 7770af
Packit Service 7770af
    // Assert string boundaries (/\Z|\z|\A/)
Packit Service 7770af
    // There are zero-width positive lookaheads
Packit Service 7770af
    const char* end_of_line(const char* src);
Packit Service 7770af
Packit Service 7770af
    // Assert end_of_file boundary (/\z/)
Packit Service 7770af
    const char* end_of_file(const char* src);
Packit Service 7770af
    // const char* start_of_string(const char* src);
Packit Service 7770af
Packit Service 7770af
    // Type definition for prelexer functions
Packit Service 7770af
    typedef const char* (*prelexer)(const char*);
Packit Service 7770af
Packit Service 7770af
    //####################################
Packit Service 7770af
    // BASIC "REGEX" CONSTRUCTORS
Packit Service 7770af
    //####################################
Packit Service 7770af
Packit Service 7770af
    // Match a single character literal.
Packit Service 7770af
    // Regex equivalent: /(?:x)/
Packit Service 7770af
    template <char chr>
Packit Service 7770af
    const char* exactly(const char* src) {
Packit Service 7770af
      return *src == chr ? src + 1 : 0;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    // Match the full string literal.
Packit Service 7770af
    // Regex equivalent: /(?:literal)/
Packit Service 7770af
    template <const char* str>
Packit Service 7770af
    const char* exactly(const char* src) {
Packit Service 7770af
      if (str == NULL) return 0;
Packit Service 7770af
      const char* pre = str;
Packit Service 7770af
      if (src == NULL) return 0;
Packit Service 7770af
      // there is a small chance that the search string
Packit Service 7770af
      // is longer than the rest of the string to look at
Packit Service 7770af
      while (*pre && *src == *pre) {
Packit Service 7770af
        ++src, ++pre;
Packit Service 7770af
      }
Packit Service 7770af
      // did the matcher finish?
Packit Service 7770af
      return *pre == 0 ? src : 0;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
Packit Service 7770af
    // Match the full string literal.
Packit Service 7770af
    // Regex equivalent: /(?:literal)/i
Packit Service 7770af
    // only define lower case alpha chars
Packit Service 7770af
    template <const char* str>
Packit Service 7770af
    const char* insensitive(const char* src) {
Packit Service 7770af
      if (str == NULL) return 0;
Packit Service 7770af
      const char* pre = str;
Packit Service 7770af
      if (src == NULL) return 0;
Packit Service 7770af
      // there is a small chance that the search string
Packit Service 7770af
      // is longer than the rest of the string to look at
Packit Service 7770af
      while (*pre && (*src == *pre || *src+32 == *pre)) {
Packit Service 7770af
        ++src, ++pre;
Packit Service 7770af
      }
Packit Service 7770af
      // did the matcher finish?
Packit Service 7770af
      return *pre == 0 ? src : 0;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    // Match for members of char class.
Packit Service 7770af
    // Regex equivalent: /[axy]/
Packit Service 7770af
    template <const char* char_class>
Packit Service 7770af
    const char* class_char(const char* src) {
Packit Service 7770af
      const char* cc = char_class;
Packit Service 7770af
      while (*cc && *src != *cc) ++cc;
Packit Service 7770af
      return *cc ? src + 1 : 0;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    // Match for members of char class.
Packit Service 7770af
    // Regex equivalent: /[axy]+/
Packit Service 7770af
    template <const char* char_class>
Packit Service 7770af
    const char* class_chars(const char* src) {
Packit Service 7770af
      const char* p = src;
Packit Service 7770af
      while (class_char<char_class>(p)) ++p;
Packit Service 7770af
      return p == src ? 0 : p;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    // Match for members of char class.
Packit Service 7770af
    // Regex equivalent: /[^axy]/
Packit Service 7770af
    template <const char* neg_char_class>
Packit Service 7770af
    const char* neg_class_char(const char* src) {
Packit Service 7770af
      if (*src == 0) return 0;
Packit Service 7770af
      const char* cc = neg_char_class;
Packit Service 7770af
      while (*cc && *src != *cc) ++cc;
Packit Service 7770af
      return *cc ? 0 : src + 1;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    // Match for members of char class.
Packit Service 7770af
    // Regex equivalent: /[^axy]+/
Packit Service 7770af
    template <const char* neg_char_class>
Packit Service 7770af
    const char* neg_class_chars(const char* src) {
Packit Service 7770af
      const char* p = src;
Packit Service 7770af
      while (neg_class_char<neg_char_class>(p)) ++p;
Packit Service 7770af
      return p == src ? 0 : p;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    // Match all except the supplied one.
Packit Service 7770af
    // Regex equivalent: /[^x]/
Packit Service 7770af
    template <const char chr>
Packit Service 7770af
    const char* any_char_but(const char* src) {
Packit Service 7770af
      return (*src && *src != chr) ? src + 1 : 0;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    // Succeeds if the matcher fails.
Packit Service 7770af
    // Aka. zero-width negative lookahead.
Packit Service 7770af
    // Regex equivalent: /(?!literal)/
Packit Service 7770af
    template <prelexer mx>
Packit Service 7770af
    const char* negate(const char* src) {
Packit Service 7770af
      return mx(src) ? 0 : src;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    // Succeeds if the matcher succeeds.
Packit Service 7770af
    // Aka. zero-width positive lookahead.
Packit Service 7770af
    // Regex equivalent: /(?=literal)/
Packit Service 7770af
    // just hangs around until we need it
Packit Service 7770af
    template <prelexer mx>
Packit Service 7770af
    const char* lookahead(const char* src) {
Packit Service 7770af
      return mx(src) ? src : 0;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    // Tries supplied matchers in order.
Packit Service 7770af
    // Succeeds if one of them succeeds.
Packit Service 7770af
    // Regex equivalent: /(?:FOO|BAR)/
Packit Service 7770af
    template <const prelexer mx>
Packit Service 7770af
    const char* alternatives(const char* src) {
Packit Service 7770af
      const char* rslt;
Packit Service 7770af
      if ((rslt = mx(src))) return rslt;
Packit Service 7770af
      return 0;
Packit Service 7770af
    }
Packit Service 7770af
    template <const prelexer mx1, const prelexer mx2, const prelexer... mxs>
Packit Service 7770af
    const char* alternatives(const char* src) {
Packit Service 7770af
      const char* rslt;
Packit Service 7770af
      if ((rslt = mx1(src))) return rslt;
Packit Service 7770af
      return alternatives<mx2, mxs...>(src);
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    // Tries supplied matchers in order.
Packit Service 7770af
    // Succeeds if all of them succeeds.
Packit Service 7770af
    // Regex equivalent: /(?:FOO)(?:BAR)/
Packit Service 7770af
    template <const prelexer mx1>
Packit Service 7770af
    const char* sequence(const char* src) {
Packit Service 7770af
      const char* rslt = src;
Packit Service 7770af
      if (!(rslt = mx1(rslt))) return 0;
Packit Service 7770af
      return rslt;
Packit Service 7770af
    }
Packit Service 7770af
    template <const prelexer mx1, const prelexer mx2, const prelexer... mxs>
Packit Service 7770af
    const char* sequence(const char* src) {
Packit Service 7770af
      const char* rslt = src;
Packit Service 7770af
      if (!(rslt = mx1(rslt))) return 0;
Packit Service 7770af
      return sequence<mx2, mxs...>(rslt);
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
Packit Service 7770af
    // Match a pattern or not. Always succeeds.
Packit Service 7770af
    // Regex equivalent: /(?:literal)?/
Packit Service 7770af
    template <prelexer mx>
Packit Service 7770af
    const char* optional(const char* src) {
Packit Service 7770af
      const char* p = mx(src);
Packit Service 7770af
      return p ? p : src;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    // Match zero or more of the patterns.
Packit Service 7770af
    // Regex equivalent: /(?:literal)*/
Packit Service 7770af
    template <prelexer mx>
Packit Service 7770af
    const char* zero_plus(const char* src) {
Packit Service 7770af
      const char* p = mx(src);
Packit Service 7770af
      while (p) src = p, p = mx(src);
Packit Service 7770af
      return src;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    // Match one or more of the patterns.
Packit Service 7770af
    // Regex equivalent: /(?:literal)+/
Packit Service 7770af
    template <prelexer mx>
Packit Service 7770af
    const char* one_plus(const char* src) {
Packit Service 7770af
      const char* p = mx(src);
Packit Service 7770af
      if (!p) return 0;
Packit Service 7770af
      while (p) src = p, p = mx(src);
Packit Service 7770af
      return src;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    // Match mx non-greedy until delimiter.
Packit Service 7770af
    // Other prelexers are greedy by default.
Packit Service 7770af
    // Regex equivalent: /(?:$mx)*?(?=$delim)\b/
Packit Service 7770af
    template <prelexer mx, prelexer delim>
Packit Service 7770af
    const char* non_greedy(const char* src) {
Packit Service 7770af
      while (!delim(src)) {
Packit Service 7770af
        const char* p = mx(src);
Packit Service 7770af
        if (p == src) return 0;
Packit Service 7770af
        if (p == 0) return 0;
Packit Service 7770af
        src = p;
Packit Service 7770af
      }
Packit Service 7770af
      return src;
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    //####################################
Packit Service 7770af
    // ADVANCED "REGEX" CONSTRUCTORS
Packit Service 7770af
    //####################################
Packit Service 7770af
Packit Service 7770af
    // Match with word boundary rule.
Packit Service 7770af
    // Regex equivalent: /(?:$mx)\b/i
Packit Service 7770af
    template <const char* str>
Packit Service 7770af
    const char* keyword(const char* src) {
Packit Service 7770af
      return sequence <
Packit Service 7770af
               insensitive < str >,
Packit Service 7770af
               word_boundary
Packit Service 7770af
             >(src);
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    // Match with word boundary rule.
Packit Service 7770af
    // Regex equivalent: /(?:$mx)\b/
Packit Service 7770af
    template <const char* str>
Packit Service 7770af
    const char* word(const char* src) {
Packit Service 7770af
      return sequence <
Packit Service 7770af
               exactly < str >,
Packit Service 7770af
               word_boundary
Packit Service 7770af
             >(src);
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
    template <char chr>
Packit Service 7770af
    const char* loosely(const char* src) {
Packit Service 7770af
      return sequence <
Packit Service 7770af
               optional_spaces,
Packit Service 7770af
               exactly < chr >
Packit Service 7770af
             >(src);
Packit Service 7770af
    }
Packit Service 7770af
    template <const char* str>
Packit Service 7770af
    const char* loosely(const char* src) {
Packit Service 7770af
      return sequence <
Packit Service 7770af
               optional_spaces,
Packit Service 7770af
               exactly < str >
Packit Service 7770af
             >(src);
Packit Service 7770af
    }
Packit Service 7770af
Packit Service 7770af
  }
Packit Service 7770af
}
Packit Service 7770af
Packit Service 7770af
#endif