Commit 04188848 by Aaron Leung

More C++ stuff. Don't try to compile the Node stuff yet.

parent 0287c9a8
#include <vector>
#include "node.hpp"
namespace Sass {
struct Document {
using std::vector;
char* source;
unsigned int position;
vector<Node> statements;
};
}
\ No newline at end of file
#include <vector>
#include "token.hpp"
namespace Sass {
struct Node {
\ No newline at end of file
#include <cctype>
#include "prelexer.hpp"
namespace Sass {
......@@ -7,11 +8,118 @@ namespace Sass {
char *epsilon(char *src) {
return src;
}
// Matches the empty string.
char *empty(char *src) {
return *src ? 0 : src;
}
// Match a single character satisfying the ctype predicates.
char* space(char* src) { return std::isspace(*src) ? src+1 : 0; }
char* alpha(char* src) { return std::isalpha(*src) ? src+1 : 0; }
char* digit(char* src) { return std::isdigit(*src) ? src+1 : 0; }
char* xdigit(char* src) { return std::isxdigit(*src) ? src+1 : 0; }
char* alnum(char* src) { return std::isalnum(*src) ? src+1 : 0; }
char* punct(char* src) { return std::ispunct(*src) ? src+1 : 0; }
// Match multiple ctype characters.
char* spaces(char* src) { return one_plus<space>(src); }
char* alphas(char* src) { return one_plus<alpha>(src); }
char* digits(char* src) { return one_plus<digit>(src); }
char* xdigits(char* src) { return one_plus<xdigit>(src); }
char* alnums(char* src) { return one_plus<alnum>(src); }
char* puncts(char* src) { return one_plus<punct>(src); }
// Match a line comment.
extern const char slash_slash[] = "//";
char* line_comment(char* src) { return to_endl<slash_slash>(src); }
// Match a block comment.
extern const char slash_star[] = "/*";
extern const char star_slash[] = "*/";
char* block_comment(char* src) {
return delimited_by<slash_star, star_slash, false>(src);
}
// Match double- and single-quoted strings.
char* double_quoted_string(char* src) {
return delimited_by<'"', '"', true>(src);
}
char* single_quoted_string(char* src) {
return delimited_by<'\'', '\'', true>(src);
}
char* string_constant(char* src) {
return alternatives<double_quoted_string, single_quoted_string>(src);
}
// Match interpolants.
extern const char hash_lbrace[] = "#{";
extern const char rbrace[] = "}";
char* interpolant(char* src) {
return delimited_by<hash_lbrace, rbrace, false>(src);
}
// Match CSS identifiers.
char* identifier(char* src) {
return sequence< optional< exactly<'-'> >,
alternatives< alpha, exactly<'_'> >,
zero_plus< alternatives< alnum,
exactly<'-'>,
exactly<'_'> > > >(src);
}
// Match CSS '@' keywords.
char* at_keyword(char* src) {
return sequence<exactly<'@'>, identifier>(src);
}
char* name(char* src) {
return one_plus< alternatives< alnum,
exactly<'-'>,
exactly<'_'> > >(src);
}
// Match CSS id names.
char* id_name(char* src) {
return sequence<exactly<'#'>, name>(src);
}
// Match CSS class names.
char* class_name(char* src) {
return sequence<exactly<'.'>, identifier>(src);
}
// Match CSS numeric constants.
extern const char sign[] = "-+";
char* unsigned_number(char* src) {
return alternatives<sequence< zero_plus<digits>,
exactly<'.'>,
one_plus<digits> >,
digits>(src);
}
char* number(char* src) {
return sequence< optional< class_char<sign> >, unsigned_number>(src);
}
char* percentage(char* src) {
return sequence< number, exactly<'%'> >(src);
}
char* dimension(char* src) {
return sequence<number, identifier>(src);
}
// Match CSS uri specifiers.
extern const char url_call[] = "url(";
char* uri(char* src) {
return sequence< exactly<url_call>,
optional<spaces>,
string_constant,
optional<spaces>,
exactly<')'> >(src);
}
// Match CSS function call openers.
char* function(char* src) {
return sequence< identifier, exactly<'('> >(src);
}
// Match CSS attribute-matching operators.
extern const char tilde_equal[] = "~=";
extern const char pipe_equal[] = "|=";
extern const char caret_equal[] = "^=";
extern const char dollar_equal[] = "$=";
extern const char star_equal[] = "*=";
char* exact_match(char* src) { return exactly<'='>(src); }
char* class_match(char* src) { return exactly<tilde_equal>(src); }
char* dash_match(char* src) { return exactly<pipe_equal>(src); }
char* prefix_match(char* src) { return exactly<caret_equal>(src); }
char* suffix_match(char* src) { return exactly<dollar_equal>(src); }
char* substring_match(char* src) { return exactly<star_equal>(src); }
}
}
\ No newline at end of file
......@@ -2,58 +2,80 @@ namespace Sass {
namespace Prelexer {
typedef int (*ctype_predicate)(int);
typedef char *(*prelexer)(char *);
typedef char* (*prelexer)(char*);
// Match a single character literal.
template <char pre>
char *exactly(char *src) {
char* exactly(char* src) {
return *src == pre ? src + 1 : 0;
}
// Match a string constant.
template <const char *prefix>
char *exactly(char *src) {
char *pre = prefix;
template <const char* prefix>
char* exactly(char* src) {
const char* pre = prefix;
while (*pre && *src == *pre) ++src, ++pre;
return *pre ? 0 : src;
}
// Match a single character that satifies the supplied ctype predicate.
template <ctype_predicate pred>
char *class_char(char *src) {
char* class_char(char* src) {
return pred(*src) ? src + 1 : 0;
}
// Match a single character that is a member of the supplied class.
template <const char *char_class>
char *class_char(char *src) {
char *cc = char_class;
template <const char* char_class>
char* class_char(char* src) {
const char* cc = char_class;
while (*cc && *src != *cc) ++cc;
return *cc ? src + 1 : 0;
}
// Match a sequence of characters that all satisfy the supplied ctype predicate.
template <ctype_predicate pred>
char *class_chars(char *src) {
char *p = src;
char* class_chars(char* src) {
char* p = src;
while (pred(*p)) ++p;
return p == src ? 0 : p;
}
// Match a sequence of characters that are all members of the supplied class.
template <const char *char_class>
char *class_chars(char *src) {
char *p = src;
template <const char* char_class>
char* class_chars(char* src) {
char* p = src;
while (class_char<char_class>(p)) ++p;
return p == src ? 0 : p;
}
// Match a sequence of characters up to the next newline.
template <const char* prefix>
char* to_endl(char* src) {
if (!(src = exactly<prefix>(src))) return 0;
while (*src && *src != '\n') ++src;
return src;
}
// Match a sequence of characters delimited by the supplied chars.
template <char beg, char end, bool esc>
char* delimited_by(char* src) {
src = exactly<beg>(src);
if (!src) return 0;
char* stop;
while (1) {
if (!*src) return 0;
stop = exactly<end>(src);
if (stop && (!esc || *(src - 1) != '\\')) return stop;
src = stop ? stop : src + 1;
}
}
// Match a sequence of characters delimited by the supplied strings.
template <const char *beg, const char *end, bool esc>
char *delimited_by(char *src) {
template <const char* beg, const char* end, bool esc>
char* delimited_by(char* src) {
src = exactly<beg>(src);
if (!src) return 0;
char *stop;
char* stop;
while (1) {
if (!*src) return 0;
stop = exactly<end>(src);
......@@ -63,37 +85,37 @@ namespace Sass {
}
// Matches zero characters (always succeeds without consuming input).
char *epsilon(char *);
char* epsilon(char*);
// Matches the empty string.
char *empty(char *);
char* empty(char*);
// Succeeds of the supplied matcher fails, and vice versa.
template <prelexer mx>
char *negate(char *src) {
char* negate(char* src) {
return mx(src) ? 0 : src;
}
// Tries the matchers in sequence and returns the first match (or none)
template <prelexer mx1, prelexer mx2>
char *alternatives(char *src) {
char *rslt;
char* alternatives(char* src) {
char* rslt;
(rslt = mx1(src)) || (rslt = mx2(src));
return rslt;
}
// Same as above, but with 3 arguments.
template <prelexer mx1, prelexer mx2, prelexer mx3>
char *alternatives(char *src) {
char *rslt;
char* alternatives(char* src) {
char* rslt;
(rslt = mx1(src)) || (rslt = mx2(src)) || (rslt = mx3(src));
return rslt;
}
// Same as above, but with 4 arguments.
template <prelexer mx1, prelexer mx2, prelexer mx3, prelexer mx4>
char *alternatives(char *src) {
char *rslt;
char* alternatives(char* src) {
char* rslt;
(rslt = mx1(src)) || (rslt = mx2(src)) ||
(rslt = mx3(src)) || (rslt = mx4(src));
return rslt;
......@@ -101,37 +123,114 @@ namespace Sass {
// Tries the matchers in sequence and succeeds if they all succeed.
template <prelexer mx1, prelexer mx2>
char *sequence(char *src) {
char *rslt = src;
char* sequence(char* src) {
char* rslt = src;
(rslt = mx1(rslt)) && (rslt = mx2(rslt));
return rslt;
}
// Same as above, but with 3 arguments.
template <prelexer mx1, prelexer mx2, prelexer mx3>
char *sequence(char *src) {
char *rslt = src;
char* sequence(char* src) {
char* rslt = src;
(rslt = mx1(rslt)) && (rslt = mx2(rslt)) && (rslt = mx3(rslt));
return rslt;
}
// Same as above, but with 4 arguments.
template <prelexer mx1, prelexer mx2, prelexer mx3, prelexer mx4>
char *sequence(char *src) {
char *rslt = src;
char* sequence(char* src) {
char* rslt = src;
(rslt = mx1(rslt)) && (rslt = mx2(rslt)) &&
(rslt = mx3(rslt)) && (rslt = mx4(rslt));
return rslt;
}
// Same as above, but with 5 arguments.
template <prelexer mx1, prelexer mx2,
prelexer mx3, prelexer mx4,
prelexer mx5>
char* sequence(char* src) {
char* rslt = src;
(rslt = mx1(rslt)) && (rslt = mx2(rslt)) &&
(rslt = mx3(rslt)) && (rslt = mx4(rslt)) &&
(rslt = mx5(rslt));
return rslt;
}
// Match a pattern or not. Always succeeds.
template <prelexer mx>
char *optional(char *src) {
char *p = mx(src);
char* optional(char* src) {
char* p = mx(src);
return p ? p : src;
}
// Match zero or more of the supplied pattern
template <prelexer mx>
char* zero_plus(char* src) {
char* p = mx(src);
while (p) src = p, p = mx(src);
return src;
}
// Match one or more of the supplied pattern
template <prelexer mx>
char* one_plus(char* src) {
char* p = mx(src);
if (!p) return 0;
while (p) src = p, p = mx(src);
return src;
}
// Match a single character satisfying the ctype predicates.
char *space(char *src);
char *alpha(char *src);
char *digit(char *src);
char *xdigit(char *src);
char *alnum(char *src);
char *punct(char *src);
// Match multiple ctype characters.
char* spaces(char* src);
char* alphas(char* src);
char* digits(char* src);
char* xdigits(char* src);
char* alnums(char* src);
char* puncts(char* src);
// Match a line comment.
char* line_comment(char* src);
// Match a block comment.
char* block_comment(char* src);
// Match double- and single-quoted strings.
char* double_quoted_string(char* src);
char* single_quoted_string(char* src);
char* string_constant(char* src);
// Match interpolants.
char* interpolant(char* src);
// Match a CSS identifier.
char* identifier(char* src);
// Match CSS '@' keywords.
char* at_keyword(char* src);
// Match CSS id names.
char* id_name(char* src);
// Match CSS class names.
char* class_name(char* src);
// Match CSS numeric constants.
char* unsigned_number(char* src);
char* number(char* src);
char* percentage(char* src);
char* dimension(char* src);
// Match CSS uri specifiers.
char* uri(char* src);
// Match CSS function call openers.
char* function(char* src);
// Match CSS attribute-matching operators.
char* exact_match(char* src);
char* class_match(char* src);
char* dash_match(char* src);
char* prefix_match(char* src);
char* suffix_match(char* src);
char* substring_match(char* src);
}
}
#include <iostream>
#include <string>
#include "prelexer.hpp"
using std::cout;
using std::endl;
using std::string;
using namespace Sass::Prelexer;
extern const char msg1[] = "Matched an 'a'!";
extern const char msg2[] = "Failed to match a 'b'!";
int main() {
prelexer p = exactly<'a'>;
prelexer q = exactly<'b'>;
if (p("abcd")) cout << msg1 << endl;
if (!q("abcd")) cout << msg2 << endl;
return 0;
}
\ No newline at end of file
#include <cstdio>
#include "prelexer.hpp"
using namespace Sass::Prelexer;
void print_slice(const char *s, const char *t) {
if (t) {
printf("succeeded with %ld characters:\t", t - s);
while (s < t) putchar(*s++);
putchar('\n');
}
else {
printf("failed\n");
}
}
#define check_twice(matcher, inp1, inp2) \
(printf("Attempting to match %s\n", #matcher), \
print_slice(inp1, matcher(inp1)), \
print_slice(inp2, matcher(inp2)), \
putchar('\n'))
char num1[] = "123foogoo";
char num2[] = ".456e7";
char num3[] = "-23.45";
char ident1[] = "-webkit-box-sizing: border-box;";
char interp1[] = "#{$stuff + $more_stuff}";
char atkwd1[] = "@media screen blah blah { ... }";
char idnm1[] = "#-blah_hoo { color: red; }";
char classnm1[] = ".hux-boo23 { color: blue; }";
char percent1[] = "110%; color: red; }";
char dim1[] = "12px; color: blue; }";
char uri1[] = "url( 'www.bork.com/bork.png' )";
char ident2[] = "url ()// not a uri!";
char func1[] = "lighten(indigo, 20%)";
char exact1[] = "='blah'] { ... }";
char inc1[] = "~='foo'] { ... }";
char dash1[] = "|='bar'] { ... }";
char pre1[] = "^='hux'] { ... }";
char suf1[] = "$='baz'] { ... }";
char sub1[] = "*='bum'] { ... }";
int main() {
check_twice(identifier, ident1, num1);
check_twice(interpolant, interp1, idnm1);
check_twice(at_keyword, atkwd1, classnm1);
check_twice(id_name, idnm1, interp1);
check_twice(class_name, classnm1, num2);
check_twice(number, num1, ident1);
check_twice(number, num2, classnm1);
check_twice(number, num3, ident1);
check_twice(percentage, percent1, dim1);
check_twice(dimension, dim1, percent1);
check_twice(uri, uri1, ident2);
check_twice(function, func1, ident2);
check_twice(exact_match, exact1, inc1);
check_twice(class_match, inc1, pre1);
check_twice(dash_match, dash1, suf1);
check_twice(prefix_match, pre1, dash1);
check_twice(suffix_match, suf1, pre1);
check_twice(substring_match, sub1, suf1);
return 0;
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment