Skip to content

Commit

Permalink
Separated attributes out to have their own mark/store variable and re…
Browse files Browse the repository at this point in the history
…gs. This way, they won't conflict with captured text or backtracked text.
  • Loading branch information
jgarber committed May 20, 2009
1 parent 29714c3 commit af45e12
Show file tree
Hide file tree
Showing 18 changed files with 154 additions and 66 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG
@@ -1,5 +1,7 @@
=== Edge

* Separated attributes out to have their own mark/store variable and regs. This way, they won't conflict with captured text or backtracked text. [Jason Garber]

* Added a RedCloth::EXTENSION_LANGUAGE constant so you can tell what version of the parser you are using. [Jason Garber]

* Added a NotCompiledError to give a friendlier message when people just unpack RedCloth into their projects. [Jason Garber]
Expand Down
11 changes: 7 additions & 4 deletions Rakefile
Expand Up @@ -121,10 +121,12 @@ def ragel(target_file, source_file)
preferred_code_style = case host_language
when "R"
"F1"
else
when "C"
"T0"
else
nil
end
code_style = " -" + (@code_style || preferred_code_style)
code_style = preferred_code_style ? " -" + (@code_style || preferred_code_style) : ""
ensure_ragel_version(target_file) do
sh %{ragel #{source_file} -#{host_language}#{code_style} -o #{target_file}}
end
Expand Down Expand Up @@ -216,11 +218,12 @@ end
require 'rubygems'
require 'spec/rake/spectask'
Rake::Task[:default].prerequisites.clear
Spec::Rake::SpecTask.new(:default) do |t|
t.spec_opts = ["--color", "--require=spec/differs/inline.rb", "--diff=RedClothDiffers::Inline"]
Spec::Rake::SpecTask.new do |t|
t.spec_opts = ["--options #{File.dirname(__FILE__) + '/spec/spec.opts'}"]
t.spec_files = FileList['spec/**/*_spec.rb']
end

task :default => :spec
task :spec => [:compile]

task :remove_other_platforms do
Expand Down
19 changes: 16 additions & 3 deletions ext/redcloth_scan/redcloth.h
Expand Up @@ -49,10 +49,11 @@ VALUE red_pass(VALUE, VALUE, VALUE, ID, VALUE);
VALUE red_pass_code(VALUE, VALUE, VALUE, ID);

/* parser macros */
#define CLEAR_REGS() regs = rb_hash_new();
#define CLEAR_REGS() regs = rb_hash_new(); attr_regs = rb_hash_new();
#define RESET_REG() reg = NULL
#define MARK() reg = p;
#define MARK_B() bck = p;
#define MARK_ATTR() attr_reg = p;
#define CAT(H) rb_str_cat(H, ts, te-ts)
#define CLEAR(H) H = STR_NEW2("")
#define RSTRIP_BANG(H) rb_funcall(H, rb_intern("rstrip!"), 0)
Expand All @@ -75,13 +76,16 @@ VALUE red_pass_code(VALUE, VALUE, VALUE, ID);
#define ADD_BLOCKCODE() rb_str_append(html, red_blockcode(self, regs, block)); CLEAR(block); CLEAR_REGS()
#define ADD_EXTENDED_BLOCKCODE() rb_str_append(html, red_blockcode(self, regs, block)); CLEAR(block);
#define ASET(T, V) rb_hash_aset(regs, ID2SYM(rb_intern(T)), STR_NEW2(V));
#define AINC(T) red_inc(regs, ID2SYM(rb_intern(T)));
#define ATTR_SET(T, V) rb_hash_aset(attr_regs, ID2SYM(rb_intern(T)), STR_NEW2(V));
#define ATTR_INC(T) red_inc(attr_regs, ID2SYM(rb_intern(T)));
#define INC(N) N++;
#define SET_ATTRIBUTES() \
SET_ATTRIBUTE("class_buf", "class"); \
SET_ATTRIBUTE("id_buf", "id"); \
SET_ATTRIBUTE("lang_buf", "lang"); \
SET_ATTRIBUTE("style_buf", "style");
SET_ATTRIBUTE("style_buf", "style"); \
rb_funcall(regs, rb_intern("merge!"), 1, attr_regs); \
attr_regs = rb_hash_new();
#define SET_ATTRIBUTE(B, A) \
if (rb_hash_aref(regs, ID2SYM(rb_intern(B))) != Qnil) rb_hash_aset(regs, ID2SYM(rb_intern(A)), rb_hash_aref(regs, ID2SYM(rb_intern(B))));
#define TRANSFORM(T) \
Expand All @@ -108,6 +112,15 @@ VALUE red_pass_code(VALUE, VALUE, VALUE, ID);
} else { \
rb_hash_aset(regs, ID2SYM(rb_intern(T)), Qnil); \
}
#define STORE_ATTR(T) \
if (p > attr_reg && attr_reg >= ts) { \
VALUE str = STR_NEW(attr_reg, p-attr_reg); \
rb_hash_aset(attr_regs, ID2SYM(rb_intern(T)), str); \
/*printf("STORE_B(" T ") '%s' (p:'%s' reg:'%s')\n", RSTRING_PTR(str), p, reg);*/ \
} else { \
rb_hash_aset(attr_regs, ID2SYM(rb_intern(T)), Qnil); \
}

#define STORE_URL(T) \
if (p > reg && reg >= ts) { \
char punct = 1; \
Expand Down
3 changes: 2 additions & 1 deletion ext/redcloth_scan/redcloth_attributes.c.rl
Expand Up @@ -24,8 +24,9 @@ redcloth_attribute_parser(machine, self, p, pe)
char *p, *pe;
{
int cs, act;
char *ts = 0, *te = 0, *reg = 0, *bck = NULL, *eof = NULL;
char *ts = 0, *te = 0, *reg = 0, *bck = NULL, *attr_reg = NULL, *eof = NULL;
VALUE regs = rb_hash_new();
VALUE attr_regs = rb_hash_new();

%% write init;

Expand Down
14 changes: 1 addition & 13 deletions ext/redcloth_scan/redcloth_attributes.java.rl
Expand Up @@ -35,19 +35,6 @@ public class RedclothAttributes extends RedclothScanService.Base {

%% write data nofinal;

public void SET_ATTRIBUTES() {
SET_ATTRIBUTE("class_buf", "class");
SET_ATTRIBUTE("id_buf", "id");
SET_ATTRIBUTE("lang_buf", "lang");
SET_ATTRIBUTE("style_buf", "style");
}

public void SET_ATTRIBUTE(String B, String A) {
if(!((RubyHash)regs).aref(runtime.newSymbol(B)).isNil()) {
((RubyHash)regs).aset(runtime.newSymbol(A), ((RubyHash)regs).aref(runtime.newSymbol(B)));
}
}

private int machine;

public RedclothAttributes(int machine, IRubyObject self, byte[] data, int p, int pe) {
Expand All @@ -66,6 +53,7 @@ public class RedclothAttributes extends RedclothScanService.Base {
this.orig_pe = this.pe;

this.regs = RubyHash.newHash(runtime);
this.attr_regs = RubyHash.newHash(runtime);
this.machine = machine;
}

Expand Down
1 change: 1 addition & 0 deletions ext/redcloth_scan/redcloth_attributes.rb.rl
Expand Up @@ -25,6 +25,7 @@ module RedCloth
def redcloth_attribute_parser(cs, data)
@data = data + "\0"
@regs = {}
@attr_regs = {}
@p = 0
@pe = @data.length

Expand Down
5 changes: 1 addition & 4 deletions ext/redcloth_scan/redcloth_attributes.rl
Expand Up @@ -7,10 +7,7 @@

machine redcloth_attributes;

C2_CLAS = ( "(" ( [^)#]+ >A %{ STORE("class_buf"); } )? ("#" [^)]+ >A %{STORE("id_buf");} )? ")" ) ;
C2_LNGE = ( "[" [^\[\]]+ >A %{ STORE("lang_buf"); } "]" ) ;
C2_STYL = ( "{" [^}]+ >A %{ STORE("style_buf"); } "}" ) ;
C2 = ( C2_CLAS | C2_STYL | C2_LNGE )+ ;
C2 = ( C_CLAS | C_STYL | C_LNGE )+ ;

mtext_with_attributes = ( C2 mtext >A %T ) >X ;

Expand Down
36 changes: 19 additions & 17 deletions ext/redcloth_scan/redcloth_common.rl
Expand Up @@ -4,6 +4,8 @@

action A { MARK(); }
action B { MARK_B(); }
action ATTR { MARK_ATTR(); }
action SET_ATTR { SET_ATTRIBUTES(); }
action T { STORE("text"); }
action X { CLEAR_REGS(); RESET_REG(); }
action cat { CAT(block); }
Expand All @@ -13,29 +15,29 @@
default = ^0 ;
EOF = 0 ;

# textile modifiers
A_LEFT = "<" %{ ASET("align", "left"); } ;
A_RIGHT = ">" %{ ASET("align", "right"); } ;
A_JUSTIFIED = "<>" %{ ASET("align", "justify"); } ;
A_CENTER = "=" %{ ASET("align", "center"); } ;
A_PADLEFT = "(" >A %{ AINC("padding-left"); } ;
A_PADRIGHT = ")" >A %{ AINC("padding-right"); } ;
# textile element attributes
A_LEFT = "<" %{ ATTR_SET("align", "left"); } ;
A_RIGHT = ">" %{ ATTR_SET("align", "right"); } ;
A_JUSTIFIED = "<>" %{ ATTR_SET("align", "justify"); } ;
A_CENTER = "=" %{ ATTR_SET("align", "center"); } ;
A_PADLEFT = "(" %{ ATTR_INC("padding-left"); } ;
A_PADRIGHT = ")" %{ ATTR_INC("padding-right"); } ;
A_HLGN = ( A_LEFT | A_RIGHT | A_JUSTIFIED | A_CENTER | A_PADLEFT | A_PADRIGHT ) ;
A_LIMIT = ( A_LEFT | A_CENTER | A_RIGHT ) ;
A_VLGN = ( "-" %{ ASET("vertical-align", "middle"); } | "^" %{ ASET("vertical-align", "top"); } | "~" %{ ASET("vertical-align", "bottom"); } ) ;
C_CLAS = ( "(" ( [^)#]+ >A %{ STORE("class"); } )? ("#" [^)]+ >A %{STORE("id");} )? ")" ) ;
C_LNGE = ( "[" [^\]]+ >A %{ STORE("lang"); } "]" ) ;
C_STYL = ( "{" [^}]+ >A %{ STORE("style"); } "}" ) ;
S_CSPN = ( "\\" [0-9]+ >A %{ STORE("colspan"); } ) ;
S_RSPN = ( "/" [0-9]+ >A %{ STORE("rowspan"); } ) ;
D_HEADER = "_" %{ ASET("th", "true"); } ;
A_VLGN = ( "-" %{ ATTR_SET("vertical-align", "middle"); } | "^" %{ ATTR_SET("vertical-align", "top"); } | "~" %{ ATTR_SET("vertical-align", "bottom"); } ) ;
C_CLAS = ( "(" ( [^)#]+ >ATTR %{ STORE_ATTR("class"); } )? ("#" [^)]+ >ATTR %{STORE_ATTR("id");} )? ")" ) ;
C_LNGE = ( "[" [^\]]+ >ATTR %{ STORE_ATTR("lang"); } "]" ) ;
C_STYL = ( "{" [^}]+ >ATTR %{ STORE_ATTR("style"); } "}" ) ;
S_CSPN = ( "\\" [0-9]+ >ATTR %{ STORE_ATTR("colspan"); } ) ;
S_RSPN = ( "/" [0-9]+ >ATTR %{ STORE_ATTR("rowspan"); } ) ;
D_HEADER = "_" %{ ATTR_SET("th", "true"); } ;
A = ( ( A_HLGN | A_VLGN )* ) ;
A2 = ( A_LIMIT? ) ;
S = ( S_CSPN | S_RSPN )* ;
C = ( C_CLAS | C_STYL | C_LNGE )* ;
D = ( D_HEADER ) ;
N_CONT = "_" %{ ASET("list_continue", "true"); };
N_NUM = digit+ >A %{ STORE("start"); };
N_CONT = "_" %{ ATTR_SET("list_continue", "true"); };
N_NUM = digit+ >ATTR %{ STORE_ATTR("start"); };
N = ( N_CONT | N_NUM )? ;
PUNCT = ( "!" | '"' | "#" | "$" | "%" | "&" | "'" | "," | "-" | "." | "/" | ":" | ";" | "=" | "?" | "\\" | "^" | "`" | "|" | "~" | "[" | "]" | "(" | ")" | "<" ) ;
dotspace = ("." " "*) ;
Expand Down Expand Up @@ -106,7 +108,7 @@
uri = (target | absolute_uri | absolute_path | rel_path) ;

# common
title = ( '(' default+ >A %{ STORE("title"); } :> ')' ) ;
title = ( '(' default+ >ATTR %{ STORE_ATTR("title"); } :> ')' ) ;
word = ( alnum | safe | " " ) ;
mspace = ( ( " " | "\t" | LF )+ ) -- LF{2} ;
mtext = ( chars (mspace chars)* ) ;
Expand Down
4 changes: 3 additions & 1 deletion ext/redcloth_scan/redcloth_inline.c.rl
Expand Up @@ -96,6 +96,7 @@ red_block(VALUE self, VALUE regs, VALUE block, VALUE refs)
VALUE sym_text = ID2SYM(rb_intern("text"));
VALUE btype = rb_hash_aref(regs, ID2SYM(rb_intern("type")));
block = rb_funcall(block, rb_intern("strip"), 0);
VALUE attr_regs = rb_hash_new();
if ((!NIL_P(block)) && !NIL_P(btype))
{
method = rb_str_intern(btype);
Expand Down Expand Up @@ -147,10 +148,11 @@ redcloth_inline(self, p, pe, refs)
VALUE refs;
{
int cs, act;
char *ts = NULL, *te = NULL, *reg = NULL, *eof = NULL;
char *ts = NULL, *te = NULL, *reg = NULL, *attr_reg = NULL, *eof = NULL;
char *orig_p = p;
VALUE block = STR_NEW2("");
VALUE regs = Qnil;
VALUE attr_regs = Qnil;

%% write init;

Expand Down
3 changes: 2 additions & 1 deletion ext/redcloth_scan/redcloth_inline.java.rl
Expand Up @@ -87,7 +87,7 @@ public class RedclothInline extends RedclothScanService.Base {
return regs;
}

public void PASS_CODE(IRubyObject H, String A, String T, int O) {
public void PASS_CODE(IRubyObject H, String A, String T) {
((RubyString)H).append(red_pass_code(self, regs, runtime.newSymbol(A), T));
}

Expand Down Expand Up @@ -122,6 +122,7 @@ public class RedclothInline extends RedclothScanService.Base {
this.refs = refs;
this.block = RubyString.newEmptyString(runtime);
this.regs = runtime.getNil();
this.attr_regs = runtime.getNil();
this.opts = 0;
}

Expand Down
4 changes: 2 additions & 2 deletions ext/redcloth_scan/redcloth_inline.rl
Expand Up @@ -35,8 +35,8 @@
image_title = ( '(' mtext ')' ) ;
image_is = ( A2 C ". "? (uri image_title?) >A %{ STORE("src"); } ) ;
image_link = ( ":" uri >A %{ STORE_URL("href"); } ) ;
image = ( "!" image_is "!" %A image_link? ) >X ;
bracketed_image = ( "[!" image_is "!" %A image_link? "]" ) >X ;
image = ( "!" image_is "!" %A image_link? ) >X %SET_ATTR ;
bracketed_image = ( "[!" image_is "!" %A image_link? "]" ) >X %SET_ATTR ;

# footnotes
footno = "[" >X %A digit+ %T "]" ;
Expand Down
4 changes: 2 additions & 2 deletions ext/redcloth_scan/redcloth_scan.c.rl
Expand Up @@ -32,11 +32,11 @@ redcloth_transform(self, p, pe, refs)
{
char *orig_p = p, *orig_pe = pe;
int cs, act, nest = 0;
char *ts = NULL, *te = NULL, *reg = NULL, *bck = NULL, *eof = NULL;
char *ts = NULL, *te = NULL, *reg = NULL, *bck = NULL, *attr_reg = NULL, *eof = NULL;
VALUE html = STR_NEW2("");
VALUE table = STR_NEW2("");
VALUE block = STR_NEW2("");
VALUE regs; CLEAR_REGS()
VALUE regs, attr_regs; CLEAR_REGS()


VALUE list_layout = Qnil;
Expand Down
42 changes: 39 additions & 3 deletions ext/redcloth_scan/redcloth_scan.java.rl
Expand Up @@ -26,7 +26,22 @@ import org.jruby.util.ByteList;
public class RedclothScanService implements BasicLibraryService {

public static class Base {


public void SET_ATTRIBUTES() {
SET_ATTRIBUTE("class_buf", "class");
SET_ATTRIBUTE("id_buf", "id");
SET_ATTRIBUTE("lang_buf", "lang");
SET_ATTRIBUTE("style_buf", "style");
regs.callMethod(runtime.getCurrentContext(), "merge!", attr_regs);
attr_regs = RubyHash.newHash(runtime);
}

public void SET_ATTRIBUTE(String B, String A) {
if(!((RubyHash)regs).aref(runtime.newSymbol(B)).isNil()) {
((RubyHash)regs).aset(runtime.newSymbol(A), ((RubyHash)regs).aref(runtime.newSymbol(B)));
}
}

public void CLEAR_LIST() {
list_layout = runtime.newArray();
}
Expand Down Expand Up @@ -232,6 +247,7 @@ public class RedclothScanService implements BasicLibraryService {

public void CLEAR_REGS() {
regs = RubyHash.newHash(runtime);
attr_regs = RubyHash.newHash(runtime);
}

public void RESET_REG() {
Expand All @@ -246,6 +262,10 @@ public class RedclothScanService implements BasicLibraryService {
bck = p;
}

public void MARK_ATTR() {
attr_reg = p;
}

public void CAT(IRubyObject H) {
((RubyString)H).cat(data, ts, te-ts);
}
Expand Down Expand Up @@ -288,8 +308,9 @@ public class RedclothScanService implements BasicLibraryService {
CLEAR(block);
}

public void AINC(String T) {
red_inc(regs, runtime.newSymbol(T));

public void ATTR_INC(String T) {
red_inc(attr_regs, runtime.newSymbol(T));
}

public void INC(int N) {
Expand All @@ -305,6 +326,10 @@ public class RedclothScanService implements BasicLibraryService {
((RubyHash)regs).aset(runtime.newSymbol(T), runtime.newString(V));
}

public void ATTR_SET(String T, String V) {
((RubyHash)attr_regs).aset(runtime.newSymbol(T), runtime.newString(V));
}

public void STORE(String T) {
if(p > reg && reg >= ts) {

Expand All @@ -324,6 +349,15 @@ public class RedclothScanService implements BasicLibraryService {
}
}

public void STORE_ATTR(String T) {
if(p > attr_reg && attr_reg >= ts) {
IRubyObject str = RubyString.newString(runtime, data, attr_reg, p-attr_reg);
((RubyHash)attr_regs).aset(runtime.newSymbol(T), str);
} else {
((RubyHash)attr_regs).aset(runtime.newSymbol(T), runtime.getNil());
}
}

public IRubyObject self;
public byte[] data;
public int p, pe;
Expand All @@ -336,12 +370,14 @@ public class RedclothScanService implements BasicLibraryService {
public int te = -1;
public int reg = -1;
public int bck = -1;
public int attr_reg = -1;
public int eof = -1;

public IRubyObject html;
public IRubyObject table;
public IRubyObject block;
public IRubyObject regs;
public IRubyObject attr_regs;

public IRubyObject list_layout;
public String list_type = null;
Expand Down

0 comments on commit af45e12

Please sign in to comment.