/* * hpricot_css.rl * ragel -C hpricot_css.rl -o hpricot_css.c * * Copyright (C) 2008 why the lucky stiff */ #include #define FILTER(id) \ rb_funcall2(mod, rb_intern("" # id), fargs, fvals); \ rb_ary_clear(tmpt); \ fargs = 1 #define FILTERAUTO() \ char filt[10]; \ sprintf(filt, "%.*s", te - ts, ts); \ rb_funcall2(mod, rb_intern(filt), fargs, fvals); \ rb_ary_clear(tmpt); \ fargs = 1 #ifdef HAVE_RUBY_ENCODING_H #define STRNEW(a, len) rb_external_str_new((a), (len)) #else #define STRNEW(a, len) rb_str_new((a), (len)) #endif #define PUSH(aps, ape) rb_ary_push(tmpt, fvals[fargs++] = STRNEW(aps, ape - aps)) #define P(id) printf(id ": %.*s\n", te - ts, ts); %%{ machine hpricot_css; action a { aps = p; } action b { ape = p; PUSH(aps, ape); } action c { ape = p; aps2 = p; } action d { ape2 = p; PUSH(aps, ape); PUSH(aps2, ape2); } commas = space* "," space*; traverse = [>+~]; sdot = "\\."; utfw = alnum | "_" | "-" | (0xc4 0xa8..0xbf) | (0xc5..0xdf 0x80..0xbf) | (0xe0..0xef 0x80..0xbf 0x80..0xbf) | (0xf0..0xf4 0x80..0xbf 0x80..0xbf 0x80..0xbf); utfword = utfw+; utfname = (utfw | sdot)+; quote1 = "'" [^']* "'"; quote2 = '"' [^"]* '"'; cssid = "#" %a utfname %b; cssclass = "." %a utfname %b; cssname = "[name=" %a utfname %b "]"; cssattr = "[" %a utfname %c space* [^ \n\t]? "=" %d space* (quote1 | quote2 | [^\]]+) "]"; csstag = utfname >a %b; cssmod = ("even" | "odd" | (digit | "n" | "+" | "-")* ); csschild = ":" %a ("only" | "nth" | "last" | "first") "-child" %b ("(" %a cssmod %b ")")?; csspos = ":" %a ("nth" | "eq" | "gt" | "lt" | "first" | "last" | "even" | "odd") %b ("(" %a digit+ %b ")")?; pseudop = "(" [^)]+ ")"; pseudoq = "'" (pseudop+ | [^'()]*) "'" | '"' (pseudop+ | [^"()]*) '"' | (pseudop+ | [^"()]*); pseudo = ":" %a utfname %b ("(" %a pseudoq %b ")")?; main := |* cssid => { FILTER(ID); }; cssclass => { FILTER(CLASS); }; cssname => { FILTER(NAME); }; cssattr => { FILTER(ATTR); }; csstag => { FILTER(TAG); }; cssmod => { FILTER(MOD); }; csschild => { FILTER(CHILD); }; csspos => { FILTER(POS); }; pseudo => { FILTER(PSUEDO); }; commas => { focus = rb_ary_new3(1, node); }; traverse => { FILTERAUTO(); }; space; *|; write data nofinal; }%% VALUE hpricot_css(VALUE self, VALUE mod, VALUE str, VALUE node) { int cs, act, eof; char *p, *pe, *ts, *te, *aps, *ape, *aps2, *ape2; int fargs = 1; VALUE fvals[6]; VALUE focus = rb_ary_new3(1, node); VALUE tmpt = rb_ary_new(); rb_gc_register_address(&focus); rb_gc_register_address(&tmpt); fvals[0] = focus; if (TYPE(str) != T_STRING) rb_raise(rb_eArgError, "bad CSS selector, String only please."); StringValue(str); p = RSTRING_PTR(str); pe = p + RSTRING_LEN(str); %% write init; %% write exec; rb_gc_unregister_address(&focus); rb_gc_unregister_address(&tmpt); return focus; }