1if not modules then modules = { } end modules ['strc-rsc'] = { 2 version = 1.001, 3 comment = "companion to strc-ref.mkiv", 4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", 5 copyright = "PRAGMA ADE / ConTeXt Development Team", 6 license = "see context related readme files" 7} 8 9-- The scanner is in a separate module so that we can test without too 10-- many dependencies. 11 12-- The scanner accepts nested outer, but we don't care too much, maybe 13-- some day we will have both but currently the innermost wins. 14 15local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns 16local lpegP, lpegS, lpegCs, lpegCt, lpegCf, lpegCc, lpegC, lpegCg = lpeg.P, lpeg.S, lpeg.Cs, lpeg.Ct, lpeg.Cf, lpeg.Cc, lpeg.C, lpeg.Cg 17local find = string.find 18 19local spaces = lpegP(" ")^0 20local lparent = lpegP("(") 21local rparent = lpegP(")") 22local lbrace = lpegP("{") 23local rbrace = lpegP("}") 24local tcolon = lpegP(":::") -- component or outer 25local dcolon = lpegP("::") -- outer 26local scolon = lpegP(":") -- prefix 27local backslash = lpegP("\\") 28 29 lparent = spaces * lparent * spaces 30 rparent = spaces * rparent * spaces 31 lbrace = spaces * lbrace * spaces 32 rbrace = spaces * rbrace * spaces 33 tcolon = spaces * tcolon * spaces 34 dcolon = spaces * dcolon * spaces 35 36local endofall = spaces * lpegP(-1) 37 38----- o_token = 1 - rparent - rbrace - lparent - lbrace -- can be made more efficient 39----- a_token = 1 - rbrace 40local s_token = 1 - lparent - lbrace 41local i_token = 1 - lparent - lbrace - endofall 42local f_token = 1 - lparent - lbrace - dcolon 43local c_token = 1 - lparent - lbrace - tcolon 44 45-- experimental 46 47local o_token = lpegpatterns.nestedparents 48 + (1 - rparent - lbrace) 49local a_token = lpegpatterns.nestedbraces 50 + (1 - rbrace) 51local q_token = lpegpatterns.unsingle 52 + lpegpatterns.undouble 53 54local hastexcode = lpegCg(lpegCc("has_tex") * lpegCc(true)) -- cannot be made to work 55local component = lpegCg(lpegCc("component") * lpegCs(c_token^1)) 56local outer = lpegCg(lpegCc("outer") * lpegCs(f_token^1)) 57----- operation = lpegCg(lpegCc("operation") * lpegCs(o_token^1)) 58local operation = lpegCg(lpegCc("operation") * lpegCs(q_token + o_token^1)) 59local arguments = lpegCg(lpegCc("arguments") * lpegCs(q_token + a_token^0)) 60local special = lpegCg(lpegCc("special") * lpegCs(s_token^1)) 61local inner = lpegCg(lpegCc("inner") * lpegCs(i_token^1)) 62 63 arguments = (lbrace * arguments * rbrace)^-1 64 component = component * tcolon 65 outer = outer * dcolon 66 operation = outer^-1 * operation -- special case: page(file::1) and file::page(1) 67 inner = inner * arguments 68 special = special * lparent * (operation * arguments)^-1 * rparent 69 70local referencesplitter = spaces 71 * lpegCf (lpegCt("") * (component + outer)^-1 * (special + inner)^-1 * endofall, rawset) 72 73local prefixsplitter = lpegCs(lpegP((1-scolon)^1 * scolon)) 74 * #-scolon 75 * lpegCs(lpegP(1)^1) 76 77local componentsplitter = lpegCs(lpegP((1-scolon)^1)) 78 * scolon * #-scolon 79 * lpegCs(lpegP(1)^1) 80 81prefixsplitter = componentsplitter 82 83local function splitreference(str) 84 if str and str ~= "" then 85 local t = lpegmatch(referencesplitter,str) 86 if t then 87 local a = t.arguments 88 if a and find(a,"\\",1,true) then 89 t.has_tex = true 90 else 91 local o = t.arguments 92 if o and find(o,"\\",1,true) then 93 t.has_tex = true 94 end 95 end 96 return t 97 end 98 end 99end 100 101local function splitprefix(str) 102 return lpegmatch(prefixsplitter,str) 103end 104 105local function splitcomponent(str) 106 return lpegmatch(componentsplitter,str) 107end 108 109-- register in the right namespace 110 111structures = structures or { } 112structures.references = structures.references or { } 113local references = structures.references 114 115references.referencesplitter = referencesplitter 116references.splitreference = splitreference 117references.prefixsplitter = prefixsplitter 118references.splitprefix = splitprefix 119references.componentsplitter = componentsplitter 120references.splitcomponent = splitcomponent 121 122-- test code: 123 124-- inspect(splitreference([[component:::inner]])) 125-- inspect(splitprefix([[component:::inner]])) 126-- inspect(splitprefix([[component:inner]])) 127 128-- inspect(splitreference([[name(foo)]])) 129-- inspect(splitreference([[name{foo}]])) 130-- inspect(splitreference([[xx::name(foo, bar and me)]])) 131 132-- inspect(splitreference([[ ]])) 133-- inspect(splitreference([[ inner ]])) 134-- inspect(splitreference([[ special ( operation { argument, argument } ) ]])) 135-- inspect(splitreference([[ special ( operation { argument } ) ]])) 136-- inspect(splitreference([[ special ( operation { argument, \argument } ) ]])) 137-- inspect(splitreference([[ special ( operation { \argument } ) ]])) 138-- inspect(splitreference([[ special ( operation ) ]])) 139-- inspect(splitreference([[ special ( \operation ) ]])) 140-- inspect(splitreference([[ special ( o\peration ) ]])) 141-- inspect(splitreference([[ special ( ) ]])) 142-- inspect(splitreference([[ inner { argument } ]])) 143-- inspect(splitreference([[ inner { \argument } ]])) 144-- inspect(splitreference([[ inner { ar\gument } ]])) 145-- inspect(splitreference([[inner{a\rgument}]])) 146-- inspect(splitreference([[ inner { argument, argument } ]])) 147-- inspect(splitreference([[ inner { argument, \argument } ]])) -- fails: bug in lpeg? 148-- inspect(splitreference([[ inner { \argument, \argument } ]])) 149-- inspect(splitreference([[ outer :: ]])) 150-- inspect(splitreference([[ outer :: inner]])) 151-- inspect(splitreference([[ outer :: special (operation { argument,argument } ) ]])) 152-- inspect(splitreference([[ outer :: special (operation { } )]])) 153-- inspect(splitreference([[ outer :: special ( operation { argument, \argument } ) ]])) 154-- inspect(splitreference([[ outer :: special ( operation ) ]])) 155-- inspect(splitreference([[ outer :: special ( \operation ) ]])) 156-- inspect(splitreference([[ outer :: special ( ) ]])) 157-- inspect(splitreference([[ outer :: inner { argument } ]])) 158-- inspect(splitreference([[ special ( outer :: operation ) ]])) 159 160-- inspect(splitreference([[inner(foo,bar)]])) 161 162-- inspect(splitreference([[]])) 163-- inspect(splitreference([[inner]])) 164-- inspect(splitreference([[special(operation{argument,argument})]])) 165-- inspect(splitreference([[special(operation)]])) 166-- inspect(splitreference([[special(\operation)]])) 167-- inspect(splitreference([[special()]])) 168-- inspect(splitreference([[inner{argument}]])) 169-- inspect(splitreference([[inner{\argument}]])) 170-- inspect(splitreference([[outer::]])) 171-- inspect(splitreference([[outer::inner]])) 172-- inspect(splitreference([[outer::special(operation{argument,argument})]])) 173-- inspect(splitreference([[outer::special(operation{argument,\argument})]])) 174-- inspect(splitreference([[outer::special(operation)]])) 175-- inspect(splitreference([[outer::special(\operation)]])) 176-- inspect(splitreference([[outer::special()]])) 177-- inspect(splitreference([[outer::inner{argument}]])) 178-- inspect(splitreference([[special(outer::operation)]])) 179 180-- inspect(splitreference([[special(operation)]])) 181-- inspect(splitreference([[special(operation(whatever))]])) 182-- inspect(splitreference([[special(operation{argument,argument{whatever}})]])) 183-- inspect(splitreference([[special(operation{argument{whatever}})]])) 184 185-- inspect(splitreference([[special("operation(")]])) 186-- inspect(splitreference([[special("operation(whatever")]])) 187-- inspect(splitreference([[special(operation{"argument,argument{whatever"})]])) 188-- inspect(splitreference([[special(operation{"argument{whatever"})]])) 189 190-- inspect(splitreference([[url(http://a,b.c)]])) 191-- inspect(splitcomponent([[url(http://a,b.c)]])) 192-- inspect(splitcomponent([[url(http://a.b.c)]])) 193 194 |