|
Packit Service |
7770af |
#include "sass.hpp"
|
|
Packit Service |
7770af |
#include <cctype>
|
|
Packit Service |
7770af |
#include <iostream>
|
|
Packit Service |
7770af |
#include <iomanip>
|
|
Packit Service |
7770af |
#include "lexer.hpp"
|
|
Packit Service |
7770af |
#include "constants.hpp"
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
namespace Sass {
|
|
Packit Service |
7770af |
using namespace Constants;
|
|
Packit Service |
7770af |
|
|
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) { return exactly<'@'>(src); }
|
|
Packit Service |
7770af |
const char* kwd_dot(const char* src) { return exactly<'.'>(src); }
|
|
Packit Service |
7770af |
const char* kwd_comma(const char* src) { return exactly<','>(src); };
|
|
Packit Service |
7770af |
const char* kwd_colon(const char* src) { return exactly<':'>(src); };
|
|
Packit Service |
7770af |
const char* kwd_star(const char* src) { return exactly<'*'>(src); };
|
|
Packit Service |
7770af |
const char* kwd_plus(const char* src) { return exactly<'+'>(src); };
|
|
Packit Service |
7770af |
const char* kwd_minus(const char* src) { return exactly<'-'>(src); };
|
|
Packit Service |
7770af |
const char* kwd_slash(const char* src) { return exactly<'/'>(src); };
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
//####################################
|
|
Packit Service |
7770af |
// implement some function that do exist in the standard
|
|
Packit Service |
7770af |
// but those are locale aware which brought some trouble
|
|
Packit Service |
7770af |
// this even seems to improve performance by quite a bit
|
|
Packit Service |
7770af |
//####################################
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
bool is_alpha(const char& chr)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
return unsigned(chr - 'A') <= 'Z' - 'A' ||
|
|
Packit Service |
7770af |
unsigned(chr - 'a') <= 'z' - 'a';
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
bool is_space(const char& chr)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// adapted the technique from is_alpha
|
|
Packit Service |
7770af |
return chr == ' ' || unsigned(chr - '\t') <= '\r' - '\t';
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
bool is_digit(const char& chr)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// adapted the technique from is_alpha
|
|
Packit Service |
7770af |
return unsigned(chr - '0') <= '9' - '0';
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
bool is_xdigit(const char& chr)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// adapted the technique from is_alpha
|
|
Packit Service |
7770af |
return unsigned(chr - '0') <= '9' - '0' ||
|
|
Packit Service |
7770af |
unsigned(chr - 'a') <= 'f' - 'a' ||
|
|
Packit Service |
7770af |
unsigned(chr - 'A') <= 'F' - 'A';
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
bool is_punct(const char& chr)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// locale independent
|
|
Packit Service |
7770af |
return chr == '.';
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
bool is_alnum(const char& chr)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
return is_alpha(chr) || is_digit(chr);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// check if char is outside ascii range
|
|
Packit Service |
7770af |
bool is_unicode(const char& chr)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// check for unicode range
|
|
Packit Service |
7770af |
return unsigned(chr) > 127;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// check if char is outside ascii range
|
|
Packit Service |
7770af |
// but with specific ranges (copied from Ruby Sass)
|
|
Packit Service |
7770af |
bool is_nonascii(const char& chr)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
unsigned int cmp = unsigned(chr);
|
|
Packit Service |
7770af |
return (
|
|
Packit Service |
7770af |
(cmp >= 128 && cmp <= 15572911) ||
|
|
Packit Service |
7770af |
(cmp >= 15630464 && cmp <= 15712189) ||
|
|
Packit Service |
7770af |
(cmp >= 4036001920)
|
|
Packit Service |
7770af |
);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// check if char is within a reduced ascii range
|
|
Packit Service |
7770af |
// valid in a uri (copied from Ruby Sass)
|
|
Packit Service |
7770af |
bool is_uri_character(const char& chr)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
unsigned int cmp = unsigned(chr);
|
|
Packit Service |
7770af |
return (cmp > 41 && cmp < 127) ||
|
|
Packit Service |
7770af |
cmp == ':' || cmp == '/';
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// check if char is within a reduced ascii range
|
|
Packit Service |
7770af |
// valid for escaping (copied from Ruby Sass)
|
|
Packit Service |
7770af |
bool is_escapable_character(const char& chr)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
unsigned int cmp = unsigned(chr);
|
|
Packit Service |
7770af |
return cmp > 31 && cmp < 127;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// Match word character (look ahead)
|
|
Packit Service |
7770af |
bool is_character(const char& chr)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// valid alpha, numeric or unicode char (plus hyphen)
|
|
Packit Service |
7770af |
return is_alnum(chr) || is_unicode(chr) || chr == '-';
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
//####################################
|
|
Packit Service |
7770af |
// BASIC CLASS MATCHERS
|
|
Packit Service |
7770af |
//####################################
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// create matchers that advance the position
|
|
Packit Service |
7770af |
const char* space(const char* src) { return is_space(*src) ? src + 1 : 0; }
|
|
Packit Service |
7770af |
const char* alpha(const char* src) { return is_alpha(*src) ? src + 1 : 0; }
|
|
Packit Service |
7770af |
const char* unicode(const char* src) { return is_unicode(*src) ? src + 1 : 0; }
|
|
Packit Service |
7770af |
const char* nonascii(const char* src) { return is_nonascii(*src) ? src + 1 : 0; }
|
|
Packit Service |
7770af |
const char* digit(const char* src) { return is_digit(*src) ? src + 1 : 0; }
|
|
Packit Service |
7770af |
const char* xdigit(const char* src) { return is_xdigit(*src) ? src + 1 : 0; }
|
|
Packit Service |
7770af |
const char* alnum(const char* src) { return is_alnum(*src) ? src + 1 : 0; }
|
|
Packit Service |
7770af |
const char* punct(const char* src) { return is_punct(*src) ? src + 1 : 0; }
|
|
Packit Service |
7770af |
const char* hyphen(const char* src) { return *src && *src == '-' ? src + 1 : 0; }
|
|
Packit Service |
7770af |
const char* character(const char* src) { return is_character(*src) ? src + 1 : 0; }
|
|
Packit Service |
7770af |
const char* uri_character(const char* src) { return is_uri_character(*src) ? src + 1 : 0; }
|
|
Packit Service |
7770af |
const char* escapable_character(const char* src) { return is_escapable_character(*src) ? src + 1 : 0; }
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// Match multiple ctype characters.
|
|
Packit Service |
7770af |
const char* spaces(const char* src) { return one_plus<space>(src); }
|
|
Packit Service |
7770af |
const char* digits(const char* src) { return one_plus<digit>(src); }
|
|
Packit Service |
7770af |
const char* hyphens(const char* src) { return one_plus<hyphen>(src); }
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// Whitespace handling.
|
|
Packit Service |
7770af |
const char* no_spaces(const char* src) { return negate< space >(src); }
|
|
Packit Service |
7770af |
const char* optional_spaces(const char* src) { return zero_plus< space >(src); }
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// Match any single character.
|
|
Packit Service |
7770af |
const char* any_char(const char* src) { return *src ? src + 1 : src; }
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// Match word boundary (zero-width lookahead).
|
|
Packit Service |
7770af |
const char* word_boundary(const char* src) { return is_character(*src) || *src == '#' ? 0 : src; }
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// Match linefeed /(?:\n|\r\n?)/
|
|
Packit Service |
7770af |
const char* re_linebreak(const char* src)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// end of file or unix linefeed return here
|
|
Packit Service |
7770af |
if (*src == 0 || *src == '\n') return src + 1;
|
|
Packit Service |
7770af |
// a carriage return may optionally be followed by a linefeed
|
|
Packit Service |
7770af |
if (*src == '\r') return *(src + 1) == '\n' ? src + 2 : src + 1;
|
|
Packit Service |
7770af |
// no linefeed
|
|
Packit Service |
7770af |
return 0;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// Assert string boundaries (/\Z|\z|\A/)
|
|
Packit Service |
7770af |
// This is a zero-width positive lookahead
|
|
Packit Service |
7770af |
const char* end_of_line(const char* src)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// end of file or unix linefeed return here
|
|
Packit Service |
7770af |
return *src == 0 || *src == '\n' || *src == '\r' ? src : 0;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// Assert end_of_file boundary (/\z/)
|
|
Packit Service |
7770af |
// This is a zero-width positive lookahead
|
|
Packit Service |
7770af |
const char* end_of_file(const char* src)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// end of file or unix linefeed return here
|
|
Packit Service |
7770af |
return *src == 0 ? src : 0;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|