strc-rsc.lua /size: 8039 b    last modification: 2020-07-01 14:35
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