dyndoc-ruby-core 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. checksums.yaml +7 -0
  2. data/dyndoc/.DS_Store +0 -0
  3. data/dyndoc/Dyn/.postload +1 -0
  4. data/dyndoc/Dyn/.preload +1 -0
  5. data/dyndoc/Dyn/After.dyn +3 -0
  6. data/dyndoc/Dyn/Base.dyn +18 -0
  7. data/dyndoc/Dyn/Minimum.dyn +20 -0
  8. data/dyndoc/Model/Html/DefaultPost_html.dyn +5 -0
  9. data/dyndoc/Model/Html/DefaultPre_html.dyn +15 -0
  10. data/dyndoc/Model/Odt/DefaultPost_content.xml +3 -0
  11. data/dyndoc/Model/Odt/DefaultPost_tmpl_content.xml +3 -0
  12. data/dyndoc/Model/Odt/DefaultPre_content.xml +8 -0
  13. data/dyndoc/Model/Odt/DefaultPre_tmpl_content.xml +8 -0
  14. data/dyndoc/Model/Tex/ContentPost_tmpl.tex +1 -0
  15. data/dyndoc/Model/Tex/ContentPre_tmpl.tex +6 -0
  16. data/dyndoc/Model/Tex/DefaultPost_tmpl.tex +73 -0
  17. data/dyndoc/Model/Tex/DefaultPre_tmpl.tex +16 -0
  18. data/dyndoc/Model/Ttm/DefaultPost_tmpl.ttm +3 -0
  19. data/dyndoc/Model/Ttm/DefaultPre_tmpl.ttm +16 -0
  20. data/dyndoc/Std/Array.dyn +96 -0
  21. data/dyndoc/Std/Composer.dyn +38 -0
  22. data/dyndoc/Std/DevTag.dyn +101 -0
  23. data/dyndoc/Std/DynVar.dyn +23 -0
  24. data/dyndoc/Std/File.dyn +55 -0
  25. data/dyndoc/Std/Git.dyn +34 -0
  26. data/dyndoc/Std/List.dyn +46 -0
  27. data/dyndoc/Std/OOP.dyn +32 -0
  28. data/dyndoc/Std/Signal.dyn +18 -0
  29. data/dyndoc/Std/String.dyn +22 -0
  30. data/dyndoc/Std/Styles.dyn +1 -0
  31. data/dyndoc/Std/Test.dyn +282 -0
  32. data/dyndoc/Std/Utils.dyn +42 -0
  33. data/dyndoc/Std/Verb.dyn +5 -0
  34. data/dyndoc/Style/Notation/Math.dyn +7 -0
  35. data/dyndoc/Style/Notation/Stat/Classic.dyn +8 -0
  36. data/dyndoc/Style/Notation/Stat/Cqls.dyn +44 -0
  37. data/dyndoc/Style/Text/Std.dyn +5 -0
  38. data/dyndoc/Style/Text/StdAlias.dyn +3 -0
  39. data/dyndoc/Style/Text/StdTex.dyn +17 -0
  40. data/dyndoc/Style/Text/Txt.dyn +1 -0
  41. data/dyndoc/Tex/.postload +1 -0
  42. data/dyndoc/Tex/.preload +1 -0
  43. data/dyndoc/Tex/10pt_tmpl.tex +1 -0
  44. data/dyndoc/Tex/11pt_tmpl.tex +1 -0
  45. data/dyndoc/Tex/12pt_tmpl.tex +1 -0
  46. data/dyndoc/Tex/Article_tmpl.tex +1 -0
  47. data/dyndoc/Tex/Beamer.dyn_tex +35 -0
  48. data/dyndoc/Tex/BeamerHandout_tmpl.tex +2 -0
  49. data/dyndoc/Tex/Book_tmpl.tex +1 -0
  50. data/dyndoc/Tex/DefaultFirst_tmpl.tex +1 -0
  51. data/dyndoc/Tex/DefaultLast_tmpl.tex +8 -0
  52. data/dyndoc/Tex/Default_tmpl.tex +9 -0
  53. data/dyndoc/Tex/First_tmpl.tex +8 -0
  54. data/dyndoc/Tex/Fr_tmpl.tex +17 -0
  55. data/dyndoc/Tex/Header_tmpl.tex +3 -0
  56. data/dyndoc/Tex/InclGraph_tmpl.tex +19 -0
  57. data/dyndoc/Tex/InclSpatProc_tmpl.tex +70 -0
  58. data/dyndoc/Tex/InclSumMI_tmpl.tex +4 -0
  59. data/dyndoc/Tex/LargeA4_tmpl.tex +5 -0
  60. data/dyndoc/Tex/Last_tmpl.tex +1 -0
  61. data/dyndoc/Tex/Option_tmpl.tex +8 -0
  62. data/dyndoc/Tex/Png_tmpl.tex +1 -0
  63. data/dyndoc/Tex/RefCite2_tmpl.tex +16 -0
  64. data/dyndoc/Tex/RefCite_tmpl.tex +16 -0
  65. data/dyndoc/Tex/Report_tmpl.tex +1 -0
  66. data/dyndoc/Tex/Theorem_tmpl.tex +14 -0
  67. data/dyndoc/Tools/.DS_Store +0 -0
  68. data/dyndoc/Tools/Atom.dyn/index.dyn +42 -0
  69. data/dyndoc/Tools/AtomDyndocker.dyn/index.dyn +43 -0
  70. data/dyndoc/Tools/R/Fig.dyn +144 -0
  71. data/dyndoc/Tools/R/Tools.dyn +344 -0
  72. data/dyndoc/Tools/Tex/Beamer.dyn +204 -0
  73. data/dyndoc/Tools/Tex/BeamerSlide.dyn_tex +199 -0
  74. data/dyndoc/Tools/Tex/Pgf.dyn +115 -0
  75. data/dyndoc/Tools/Tex/Table.dyn +278 -0
  76. data/dyndoc/Tools/Tex/Tools.dyn +37 -0
  77. data/dyndoc/Tools/Tex/Verb.dyn +77 -0
  78. data/dyndoc/Tools/Web/.DS_Store +0 -0
  79. data/dyndoc/Tools/Web/Ace.dyn +54 -0
  80. data/dyndoc/Tools/Web/Code.dyn +129 -0
  81. data/dyndoc/Tools/Web/DHtmlX.dyn +39 -0
  82. data/dyndoc/Tools/Web/DataTable.dyn_html +354 -0
  83. data/dyndoc/Tools/Web/Html.dyn +286 -0
  84. data/dyndoc/Tools/Web/Html/JQuery.dyn +123 -0
  85. data/dyndoc/Tools/Web/Html/Styles.dyn +4 -0
  86. data/dyndoc/Tools/Web/JQueryTools.dyn +87 -0
  87. data/dyndoc/Tools/Web/Layout.dyn +86 -0
  88. data/dyndoc/Tools/Web/Layout/CQLS.dyn +6 -0
  89. data/dyndoc/Tools/Web/Layout/LJK.dyn +41 -0
  90. data/dyndoc/Tools/Web/TabBar.dyn +37 -0
  91. data/dyndoc/Tools/Web/Ttm.dyn +20 -0
  92. data/dyndoc/Tools/Web/Txtl.dyn +14 -0
  93. data/lib/dyndoc-core.rb +59 -0
  94. data/lib/dyndoc/base/envir.rb +541 -0
  95. data/lib/dyndoc/base/filter/call.rb +127 -0
  96. data/lib/dyndoc/base/filter/filter_mngr.rb +637 -0
  97. data/lib/dyndoc/base/filter/server.rb +882 -0
  98. data/lib/dyndoc/base/filters.rb +3 -0
  99. data/lib/dyndoc/base/helpers.rb +9 -0
  100. data/lib/dyndoc/base/helpers/core.rb +32 -0
  101. data/lib/dyndoc/base/helpers/parser.rb +188 -0
  102. data/lib/dyndoc/base/scanner.rb +886 -0
  103. data/lib/dyndoc/base/tags.rb +4 -0
  104. data/lib/dyndoc/base/tags/keys_mngr.rb +401 -0
  105. data/lib/dyndoc/base/tags/part_tag.rb +194 -0
  106. data/lib/dyndoc/base/tags/tag_mngr.rb +125 -0
  107. data/lib/dyndoc/base/tags/user_tag.rb +216 -0
  108. data/lib/dyndoc/base/tmpl.rb +6 -0
  109. data/lib/dyndoc/base/tmpl/eval.rb +581 -0
  110. data/lib/dyndoc/base/tmpl/extension.rb +337 -0
  111. data/lib/dyndoc/base/tmpl/manager.rb +450 -0
  112. data/lib/dyndoc/base/tmpl/oop.rb +57 -0
  113. data/lib/dyndoc/base/tmpl/parse_do.rb +2446 -0
  114. data/lib/dyndoc/base/tmpl/rbenvir.rb +54 -0
  115. data/lib/dyndoc/base/utils.rb +367 -0
  116. data/lib/dyndoc/common/dynArray.rb +234 -0
  117. data/lib/dyndoc/common/file.rb +52 -0
  118. data/lib/dyndoc/common/init.rb +2 -0
  119. data/lib/dyndoc/common/tilt.rb +149 -0
  120. data/lib/dyndoc/common/utils.rb +61 -0
  121. data/lib/dyndoc/common/uv.rb +163 -0
  122. data/lib/dyndoc/init/config.rb +296 -0
  123. data/lib/dyndoc/init/home.rb +9 -0
  124. data/lib/dyndoc/plugins/tex.rb +4 -0
  125. data/lib/dyndoc/plugins/tex/beamer.rb +208 -0
  126. data/lib/dyndoc/plugins/tex/tex_eval.rb +69 -0
  127. data/lib/dyndoc/plugins/tex/tex_parse_do.rb +25 -0
  128. data/lib/dyndoc/plugins/tex/tex_user_tag.rb +32 -0
  129. data/share/R/dyndocMsys2.R +5 -0
  130. data/share/R/dyndocTools.R +9 -0
  131. data/share/R/test.R +14 -0
  132. data/share/R/tools/dynArray.R +34 -0
  133. data/share/R/tools/dynCapture.R +84 -0
  134. data/share/R/tools/dynMsys2.R +54 -0
  135. data/share/julia/dynArray.jl +93 -0
  136. data/share/julia/dyndoc.jl +110 -0
  137. data/share/julia/ruby.jl +37 -0
  138. metadata +202 -0
@@ -0,0 +1,3 @@
1
+ require "dyndoc/base/filter/filter_mngr"
2
+ require "dyndoc/base/filter/call"
3
+ require "dyndoc/base/filter/server"
@@ -0,0 +1,9 @@
1
+ require 'dyndoc/base/helpers/core'
2
+
3
+ #Dyndoc.warn "path helpers",File.join(File.dirname(__FILE__),"helpers/**/*.rb").gsub('\\','/')
4
+ #Dyndoc.warn "helpers",Dir[File.join(File.dirname(__FILE__),"helpers/**/*.rb").gsub('\\','/')]
5
+
6
+ Dir[File.join(File.dirname(__FILE__),"helpers/**/*.rb").gsub('\\','/')].each{|lib|
7
+ require lib unless File.basename(lib,".rb")=="core"
8
+ }
9
+
@@ -0,0 +1,32 @@
1
+ #Inside a ruby block all the methods of the class TemplateManager are accessible
2
+ #because a new envir is created as in the body of such a method called new_envir
3
+
4
+ #The main difference between this kind of helpers and a simple file containing definition of functions
5
+ #is that these functions are executed in the Object module as a normal ruby function does.
6
+
7
+ module Dyndoc
8
+
9
+ module Ruby
10
+
11
+ module Helpers
12
+
13
+ # Helpers are functions (in fact methods) used inside a ruby block!
14
+ # Put here only system helpers!
15
+ # The user is pleased to create helpers in the dyndoc/helpers directory
16
+ # and require them by the [#helpers] tag. The following is just an example!
17
+
18
+ def hello!(who="everybody")
19
+ puts "Hello "+who+"!"
20
+ end
21
+
22
+ end
23
+
24
+ class TemplateManager
25
+
26
+ include Helpers
27
+
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,188 @@
1
+ module Dyndoc;module Ruby;module Helpers
2
+
3
+
4
+ # preprocessing for parsing a string
5
+ # convert name to #{name!} in order to be executed!
6
+ def process_bang(str)
7
+ str.gsub(/[#{FilterManager.letters}]*\:?[#{FilterManager.letters}]*\!/) {|e| "\#{" + e + "}"}
8
+ end
9
+
10
+ ## TODO: improve this by using lookbehind with Regepr
11
+ def detect_string_inside_string(str)
12
+ ary=str.split(/(\")/)
13
+ inside,res=false,[""]
14
+ ary.each_index do |cpt|
15
+ if ary[cpt]=="\"" and cpt>0 and ary[cpt-1][-1,1]!="\\" #lookbehind
16
+ if inside
17
+ res[-1] += "\"" #end of the previous string
18
+ res << "" unless cpt == ary.length-1 #new string
19
+ else
20
+ res << "\"" #beginning of a string
21
+ end
22
+ inside = !inside
23
+ else
24
+ res[-1]+=ary[cpt]
25
+ end
26
+ end
27
+ return res
28
+ end
29
+
30
+ def process_rb(str)
31
+
32
+ part=detect_string_inside_string(str)
33
+ #p part
34
+ part.each_index{|i|
35
+ delim=(i%2==0 ? "\"" : "\\\"" ) #depending on inside or outside string!!!!
36
+ part[i].gsub!(/<[\w\.\_\-]+\@>/) {|e|
37
+ "@vars.extract_raw(#{delim}"+e[1...-1]+"#{delim})[:rb]"
38
+ }
39
+ part[i].gsub!(/<([\w\.\_\-]+)((?:[\$\[][^>])+(?:(?!\$>).){0,500})?\$>/) {|e|
40
+ var=$1+"$"
41
+ #puts "process_rb:<var$>";p $1;p $2
42
+ if (arg=$2)
43
+ #@vars.extract_raw(var)[:r].arg=arg
44
+ #puts "arg";p arg;p @vars.extract_raw(var)[:r].value_with_arg
45
+ "@vars.extract_raw(#{delim}"+var+"#{delim})[:r].set_arg(#{delim}"+arg+"#{delim}).value_with_arg"
46
+ else
47
+ "@vars.extract_raw(#{delim}"+var+"#{delim})[:r].value"
48
+ end
49
+ }
50
+
51
+ part[i].gsub!(/<([\w\.\_\-]+)((?:[\&\[][^>])+(?:(?!\&>).){0,500})?\&>/) {|e|
52
+ var=$1+"&"
53
+ #puts "process_rb:<var$>";p $1;p $2
54
+ if (arg=$2)
55
+ #@vars.extract_raw(var)[:r].arg=arg
56
+ #puts "arg";p arg;p @vars.extract_raw(var)[:r].value_with_arg
57
+ "@vars.extract_raw(#{delim}"+var+"#{delim})[:jl].set_arg(#{delim}"+arg+"#{delim}).value_with_arg"
58
+ else
59
+ "@vars.extract_raw(#{delim}"+var+"#{delim})[:jl].value"
60
+ end
61
+ }
62
+ #=end
63
+ part[i].gsub!(/<[\w\.\_\-]+\:>/) {|e|
64
+ "@vars.extract_raw(#{delim}"+e[1...-2]+"#{delim})[:val][0]"
65
+ }
66
+ ## dynArray var
67
+ part[i].gsub!(/<[\w\.\_\-]+\%>/) {|e|
68
+ #p e[1...-1]
69
+ #p @vars.extract_raw(e[1...-1])
70
+ #@vars.extract_raw(e[1...-1])[:rb][0]-= 10
71
+ #(Dyndoc::Vector.get[@vars.extract_raw(e[1...-1])[:rb].ids(:rb)])[0]=10
72
+ @vars.extract_raw(e[1...-1])[:rb].wrapper(:rb)
73
+ }
74
+
75
+ }
76
+ #-| TO DEBUG: Dyndoc.warn part.join("") if part.join("")!=str
77
+ #p part.join("")
78
+ str.replace(part.join(""))
79
+
80
+ end
81
+
82
+ =begin
83
+ def process_rb(str)
84
+ #puts "str";p str
85
+ str.gsub!(/<[\w\.\_\-]+\@>/) {|e|
86
+ "@vars.extract_raw(\""+e[1...-1]+"\")[:rb]"
87
+ }
88
+ #puts "str(suite)";p str
89
+ #=begin
90
+ # str.gsub!(/<([\w\.\_\-]+)((?:[\@\[][^>])+(?:(?!\@>).)*)?\@>/) {|e|
91
+ #p $1;p $2
92
+ # arg = ( $2 ? ( $2[0,1]=="@" ? "."+$2[1..-1] : $2 ) : "" )
93
+ #p arg
94
+ # "@vars.extract_raw(\""+$1+"@\")[:rb]"+arg
95
+ # }
96
+ #=end
97
+ #=begin
98
+ # str.gsub!(/<[\w\.\_\-]+\$>/) {|e|
99
+ # "@vars.extract_raw(\""+e[1...-1]+"\")[:r].value"
100
+ # }
101
+ #=end
102
+ #=begin
103
+ str.gsub!(/<([\w\.\_\-]+)((?:[\$\[][^>])+(?:(?!\$>).){0,500})?\$>/) {|e|
104
+ var=$1+"$"
105
+ #puts "process_rb:<var$>";p $1;p $2
106
+ if (arg=$2)
107
+ #@vars.extract_raw(var)[:r].arg=arg
108
+ #puts "arg";p arg;p @vars.extract_raw(var)[:r].value_with_arg
109
+ "@vars.extract_raw(\""+var+"\")[:r].set_arg(\""+arg+"\").value_with_arg"
110
+ else
111
+ "@vars.extract_raw(\""+var+"\")[:r].value"
112
+ end
113
+ }
114
+ #=end
115
+ str.gsub!(/<[\w\.\_\-]+\:>/) {|e|
116
+ "@vars.extract_raw(\""+e[1...-2]+"\")[:val][0]"
117
+ }
118
+ #p str
119
+ end
120
+ =end
121
+
122
+ def process_r(str)
123
+ #str.gsub!(/<[\w\.\_\-]+\@>/) {|e|
124
+ # "dynVar[["+e[1...-2]+"]]"
125
+ #}
126
+ str2=str.dup
127
+ ## ruby var
128
+ str.gsub!(/<([\w\.\_\-]+)(\@)?((?:[\@\[][^>])+(?:(?!\@>).){0,500})?\@>/) {|e|
129
+ #puts "process_r: ("+$1+","+($2 ? $2 : "nil" )+","+($3 ? $3 : "nil")+")"
130
+ if $3
131
+ arg =( $3[0,1]=="@" ? "."+$3[1..-1] : $3 )
132
+ #p arg
133
+ #p "dynRbVar[\""+$1+"@\",\""+arg+"\"]"
134
+ "dynVarWithArg[[\""+$1+"\",\""+arg+"\",mode=\"@\"]]"
135
+ else
136
+ "dynVar[["+$1+",mode=\"@\","+($2 ? "FALSE" : "TRUE")+"]]"
137
+ end
138
+ }
139
+ ## Julia var
140
+ str.gsub!(/<([\w\.\_\-]+)(\&)?((?:[\&\[][^>])+(?:(?!\&>).){0,500})?\&>/) {|e|
141
+ #puts "process_r(jl): ("+$1+","+($2 ? $2 : "nil" )+","+($3 ? $3 : "nil")+")"
142
+ if $3
143
+ arg =( $3[0,1]=="&" ? "."+$3[1..-1] : $3 ) #TODO: try to apply
144
+ #p arg
145
+ #p "dynRbVar[\""+$1+"@\",\""+arg+"\"]"
146
+ "dynVarWithArg[[\""+$1+"\",\""+arg+"\",mode=\"&\"]]"
147
+ else
148
+ "dynVar[["+$1+",mode=\"&\","+($2 ? "FALSE" : "FALSE")+"]]"
149
+ end
150
+ }
151
+ ## R var
152
+ str.gsub!(/<[\w\.\_\-]+\$>/) {|e|
153
+ ".dynStack$rb"+@vars.extract_raw(e[1...-1]).object_id.abs.to_s
154
+ }
155
+ ## dynArray var
156
+ str.gsub!(/<[\w\.\_\-]+\%>/) {|e|
157
+ #p e[1...-1]
158
+ #p @vars.extract_raw(e[1...-1])
159
+ @vars.extract_raw(e[1...-1])[:rb].wrapper(:r)
160
+ }
161
+ ## Dyndoc var
162
+ str.gsub!(/<[\w\.\_\-]+\:>/) {|e|
163
+ "dynVar["+e[1...-2]+"]"
164
+ }
165
+ #-| TO DEBUG: Dyndoc.warn str if str!=str2
166
+ end
167
+
168
+ def process_jl(str)
169
+ str2=str.dup
170
+ ## dynArray var
171
+ str.gsub!(/<[\w\.\_\-]+\%>/) {|e|
172
+ #p e[1...-1]
173
+ #p @vars.extract_raw(e[1...-1])
174
+ @vars.extract_raw(e[1...-1])[:rb].wrapper(:jl)
175
+ }
176
+ #-| TO DEBUG: Dyndoc.warn str if str!=str2
177
+ end
178
+
179
+ def clean_block_without_bracket(code)
180
+ #puts "initial code";p code
181
+ if code[0][0]==:main and code[0][1] =~ /^\s*\[/ and code[-1][0]==:main and code[-1][1] =~ /\]\s*$/
182
+ code[0][1].sub!(/^(\s*)(\[)/) {|e| $1}
183
+ code[-1][1]=code[-1][1].reverse.sub(/^(\s*)(\])/) {|e| $1}.reverse
184
+ #puts "cleaned code";p code
185
+ end
186
+ end
187
+
188
+ end;end;end
@@ -0,0 +1,886 @@
1
+ # Objectif du Scanner:
2
+ # 1) Gestion du parsing en mode dtag
3
+ # .) Imbrication des blocs :dtag {%...%}
4
+ # .) Bloc texte est splitté en une alternance de blocs :main et de blocs :dtag {%...%}
5
+ # .) Sortie de process en une structure:
6
+ # ex: [[:main,"..."] [:if, [:args,"...",[...]"],[:main,"..."],:else,[:main,"..."]]
7
+ # .) NEW: un bloc peut être inséré dans un argument :args
8
+ # TODO: 1) desescaper le délimiteur dans :args
9
+ # 2) Gestion du parsing des appels fonctions @{...}@
10
+ # TODO
11
+ # 3) TODO: imbrication des modes #{} :{} et :R{} à gérer
12
+ # RMK: 1) a-t-on besoin d'autant de mode? A réfléchir mais c'est en fonction des priorités d'exécution.
13
+ # 2) Il y a 4 grands modes d'utilisation:
14
+ # a) Mode imbriqué blocks dtag : {% ...%}
15
+ # rmk: exécution d'un block intérieur après le bloc :main précédent du block principal!
16
+ # b) Mode séquentiel Part tags : %() utiles dans pour le multi-output
17
+ # c) Mode séquentiel Utilisateur : [#...]
18
+ # d) Mode imbriqué dans blocks texte : #[r,R,Rb]{}, :[R,r]{} , @{}@
19
+ # rmk: exécution des blocks intérieurs avant le block principal
20
+
21
+ require 'strscan'
22
+
23
+ if RUBY_VERSION < "1.9"
24
+
25
+ class String
26
+ alias :byteslice :"[]"
27
+ end
28
+
29
+ end
30
+
31
+ module Dyndoc
32
+ class Scanner
33
+
34
+ @@type={}
35
+
36
+ @@close={"("=>")","["=>"]","{"=>"}"}
37
+ @@open={"}"=>"{",")"=>"(","]"=>"["}
38
+
39
+ #IMPORTANT: start and close delimiters are unique and not useable inside text!
40
+ #RMK: this differs from the actual CallManager
41
+
42
+ attr_reader :scan
43
+
44
+ def initialize(type,start=nil,stop=nil,mode=nil,escape=nil)
45
+ @tag_type=type
46
+ @tag=@@type[type]
47
+ @start=@tag[:start] unless start
48
+ @start=/#{@start}/ if @start.is_a? String
49
+ @stop=@tag[:stop] unless stop
50
+ @stop=/#{@stop}/ if @stop.is_a? String
51
+ @mode=@tag[:mode] unless mode
52
+ @escape={:start=>@tag[:escape_start],:stop=>@tag[:escape_stop]} unless escape
53
+ #mode corresponds to @start[@mode[:start],@mode[:length]] and @stop[@mode[:stop],@mode[:length]]
54
+ init_strange
55
+ @scan=StringScanner.new("")
56
+ end
57
+
58
+ ######################################
59
+ # stack is a sequence of delimiters
60
+ # clean_stack selects only the associated open and closed delimiters!
61
+ #####################################
62
+ def clean_stack(stack)
63
+ open_stack,keep=[],{}
64
+ stack.each do |elt|
65
+ if elt[1]==1
66
+ open_stack << elt
67
+ else
68
+ if open_stack.empty?
69
+ ##too many closed delimiters
70
+ else
71
+ keep[elt]=true
72
+ keep[open_stack.pop]=true
73
+ end
74
+ end
75
+ end
76
+ =begin
77
+ if Dyndoc.cfg_dir[:debug]
78
+ tmp=stack.select{|elt| !keep[elt]}.select{|e| @tag_type==:call and e[2] and e[1]==1 and e[2]!='{'}
79
+ begin p @txt;p tmp end unless tmp.empty?
80
+ end
81
+ =end
82
+ stack.select{|elt| keep[elt]}
83
+ end
84
+
85
+ def token_stack
86
+ @scan.string=@txt
87
+ @scan.pos=0
88
+ stack,s=[],0
89
+ mode=-2 #stop
90
+ begin
91
+ if mode!=-1
92
+ p1=@scan.check_until(@start)
93
+ if p1
94
+ s1=@scan.pre_match.size
95
+ m1=@scan.matched
96
+ end
97
+ end
98
+ if mode!=1
99
+ p2=@scan.check_until(@stop)
100
+ if p2
101
+ s2=@scan.pre_match.size
102
+ m2=@scan.matched
103
+ end
104
+ end
105
+ if p1 and p2
106
+ mode=(s1<s2 ? 1 : -1)
107
+ elsif p2 and !p1
108
+ mode=-1
109
+ elsif !p2 and p1
110
+ mode=-3 #error
111
+ elsif !p2 and !p1
112
+ mode=-2 #stop
113
+ end
114
+ if mode==1
115
+ stack << [s1,mode,m1] unless @escape[:start] and @escape[:start].include? m1
116
+ @scan.scan_until(@start)
117
+ elsif mode==-1
118
+ s=s2
119
+ stack << [s2,mode,m2] unless @escape[:stop] and @escape[:stop].include? m2
120
+ @scan.scan_until(@stop)
121
+ end
122
+ s=@scan.pos
123
+ end while mode>-2
124
+ return clean_stack(stack)
125
+ end
126
+
127
+ def init_atom
128
+ if @tag[:atom]
129
+ @txt.gsub!(@tag[:atom][:match]){|w|
130
+ m=@tag[:atom][:match].match(w)
131
+ res=""
132
+ (1...m.size).each{|i|
133
+ res << (@tag[:atom][:replace][i] ? @tag[:atom][:replace][i] : m[i])
134
+ }
135
+ res
136
+ }
137
+ end
138
+ end
139
+
140
+ def tokenize(txt)
141
+ @txt=txt
142
+ init_atom
143
+ stack=token_stack
144
+ #p txt
145
+ #p stack
146
+ stack2=[]
147
+ root=block={:inside=>[]} #init bloc
148
+ while !stack.empty?
149
+ elt=stack.shift
150
+ #puts "stack2";p stack2
151
+ if elt[1]==1
152
+ #new bloc
153
+ parent=block
154
+ block={:type=>elt[2][0...-1],:start=>elt[0],:inside=>[]}
155
+ stack2 << [block,parent]
156
+ elsif elt[1]==-1
157
+ block,parent=stack2.pop
158
+ block[:stop]=elt[0]+elt[2].size-1
159
+ if parent[:start]
160
+ block[:start] -= parent[:start]
161
+ block[:stop] -= parent[:start]
162
+ end
163
+ parent[:inside] << block
164
+ block=parent
165
+ end
166
+ end
167
+ return (@token={:txt=> @txt,:inside=> (root[:inside])})
168
+ end
169
+
170
+ ## Extract a structure with a root block which is a text block and the child blocks which are dtag blocks.
171
+ @@strange="_[_?_]_"
172
+
173
+ def init_strange(strange=@@strange)
174
+ @strange=strange
175
+ @re_strange=/#{Regexp.escape(@strange)}/
176
+ @re_strange2=/(#{Regexp.escape(@strange)})/
177
+ end
178
+
179
+ def extract(res=nil,txt=nil,type=nil)
180
+ if res
181
+ start=0
182
+ txt2=""
183
+ ind=0
184
+ res2=res.map{|r|
185
+ txt2 << txt[start...(r[:start])]
186
+ txt2 << @@strange
187
+ ind += 1
188
+ r2={}
189
+ start=r[:stop]+1
190
+ if r[:inside].empty?
191
+ r2[:txt]=txt[(r[:start])..(r[:stop])]
192
+ r2[:type]=r[:type]
193
+ r2
194
+ else
195
+ tmp=extract(r[:inside],txt[(r[:start])..(r[:stop])],r[:type])
196
+ tmp
197
+ end
198
+ }
199
+ txt2 << txt[start..-1]
200
+ {:txt=>txt2,:type=>type,:inside=> res2}
201
+ else
202
+ res=@token[:inside].dup
203
+ return extract(res,@token[:txt])
204
+ end
205
+ end
206
+
207
+ def rebuild_after_filter(res,filter=nil)
208
+ txt=""
209
+ start=0
210
+ #p res
211
+ parts=res[:txt].split(@re_strange,-1)
212
+ ##puts "parts";p parts
213
+ ##puts "inside";p res[:inside]
214
+ res[:inside].map do |e|
215
+ txt << parts.shift
216
+
217
+ txt2= (e[:inside] ? rebuild_after_filter(e,filter) : e[:txt] )
218
+ #puts "txt2";p txt2; p [res[:type],e[:type]]
219
+ #IMPORTANT: process has to have as the second argument e[:type] corresponding to the inside_type and as the third argument res[:type] corresponding to the out_type
220
+ ##Dyndoc.warn "scan",txt2,e[:type],res[:type],(filter ? filter.process(txt2,e[:type],res[:type]) : txt2)
221
+ txt2=((filter and !(txt2=~/\[HTML\]/)) ? filter.process(txt2,e[:type],res[:type]) : txt2)
222
+ ##p txt2
223
+ txt << txt2
224
+ end
225
+ #puts "txt";p txt
226
+ txt << parts.shift unless parts.empty?
227
+ txt
228
+ end
229
+
230
+ end
231
+
232
+ class CallScanner < Scanner
233
+
234
+ @@type[:call]={
235
+ :start=>/\\?(?:\#|\#\#|@|#F|#R|#r|\:R|\:r|#Rb|#rb|\:|\:Rb|\:rb|\:jl|#jl)?\{/,
236
+ :stop=> /\\?\}/,
237
+ :mode=>{:start=>-1,:stop=>0,:length=>1},
238
+ :escape_start=>['\{'], #doivent être parsable dans start
239
+ :escape_stop=>['\}'], #doivent être parsable dans stop
240
+ }
241
+
242
+ def initialize(type=:call,start=nil,stop=nil,mode=nil,escape=nil)
243
+ super
244
+ @type_stop_filter="#!"
245
+ end
246
+ end
247
+
248
+ class DevTagScanner < Scanner
249
+
250
+ =begin TO_REMOVE
251
+ @@type[:dtag] = {
252
+ :start=>'\{%(\w*)',
253
+ :stop=> '%\}',
254
+ :keyword=>['%',''],
255
+ :block=> '[\]|]',
256
+ :mode=>{:start=>0,:stop=>-1,:length=>1}
257
+ }
258
+ =end
259
+ @@type[:dtag] = {
260
+ :start=>'\{[\#\@]([\w\:\|-]*[<>]?[=?!><]?(\.\w*)?)\]',
261
+ :stop=> '\[[\#\@]([\w\:\|-]*[<>]?[=?!><]?)\}',
262
+ :atom=>{:match=>/(\{[\#\@][\w\:\|]*)([\#\@]\})/,:replace=>{2=>"][#}"}},
263
+ :block=> '\]', #no longer |
264
+ :keyword=>['\[[\#\@]','\]'],
265
+ :mode=>{:start=>0,:stop=>-1,:length=>1}
266
+ }
267
+
268
+ def get_tag_blck
269
+ @@tagblck_set
270
+ end
271
+
272
+
273
+ def initialize(type=:dtag,start=nil,stop=nil,mode=nil,escape=nil)
274
+ super
275
+ init_tag(@tag_type) if [:dtag].include? @tag_type
276
+ end
277
+
278
+ @@tagblck_set=[:<<,:<,:do,:>>,:>,:">!",:out,:nl,:"\\n",:"r<",:"R<",:"rb<",:"m<",:"M<",:"jl<",:"r>>",:"R>>",:rverb,:"rb>>",:rbverb,:"jl>>",:jlverb,:rout,:"r>",:"R>",:"rb>",:"m>",:"M>",:"jl>",:"_<",:"_>",:"__>",:"html>",:"tex>",:"txtl>",:"ttm>",:"md>",:"adoc>",:tag,:"??",:"?",:yield,:"=",:"-",:+,:"%"]
279
+ #Rmk: when a symbol is included in another one, you have to place it before! Ex: :>> before :> and also :<< before :<
280
+
281
+ @@tagblck_dyndoc_set = [:main,:content,:before,:after,:require,:helpers,:preamble,:postamble,:style,:title,:path,:first,:last,:default,:cfg]
282
+ @@tagblck_tex_set=[:class,:optclass,:package,:texinputs]
283
+ @@tagblck_html_set=[:js,:css,:header,:footer]
284
+
285
+ TXT_DTAG=[:txt,:code,:>,:<,:<<]
286
+
287
+ @@dtag={
288
+ :dtag => {
289
+ :instr=>["newBlck","input","require","hide","format","txt",">","<","<<",">>","code","verb","if","unless","for","loop","case","var","set","def","func","meth","new","super","do","out","blck","blckAnyTag","saved","b>","call","R","r","m","M","jl","renv","rverb","rbverb","jlverb","rout","rb","eval","ifndef","tags","keys","opt","document","yield","get","part"],
290
+ :alias=>{
291
+ :vars=>:var,
292
+ :dyn=>:eval,
293
+ :rmk=>:hide,
294
+ :static => :saved,
295
+ :comment=>:hide,
296
+ :>> => [:blck,:>],
297
+ #:"b>" => [:blck, :>],
298
+ :"rb>" => [:blck, :"rb>"],
299
+ :"R>" => [:blck, :"R>"],
300
+ :"jl>" => [:blck, :"jl>"],
301
+ :"jl>>" => [:blck, :"jl>>"],
302
+ :"rb<" => [:blck, :"rb<"],
303
+ :"R<" => [:blck, :"R<"],
304
+ :"jl<" => [:blck, :"jl<"],
305
+ :"r>>" => [:blck, :"r>>"],
306
+ :"R>>" => [:blck, :"r>>"],
307
+ :"*<" => [:blck, :"*<"],
308
+ :"*>" => [:blck, :"*>"],
309
+ :"_>" => [:blck, :"_>"],
310
+ :"tex>" => [:blck, :"tex>"],
311
+ :"html>" => [:blck, :"html>"],
312
+ :"txtl>" => [:blck, :"txtl>"],
313
+ :"md>" => [:blck, :"md>"],
314
+ :"adoc>" => [:blck, :"adoc>"],
315
+ :"ttm>" => [:blck, :"ttm>"]
316
+ },
317
+ :empty_keyword=>["?","empty"],
318
+ :keyword=>{
319
+ :document => @@tagblck_dyndoc_set + @@tagblck_tex_set + @@tagblck_html_set,
320
+ :if=> [:else,:elsif,:if,:unless],
321
+ :unless=> [:else,:elsif,:if,:unless],
322
+ :for=>[],
323
+ :loop=>[:break],
324
+ :case=>[:when,:else],
325
+ :var=>[:","],
326
+ :set=>[],
327
+ :def=>[:",",:binding],
328
+ :meth=>[:","],
329
+ :new=>[:",",:of,:in,:blck],
330
+ :super=>[:",",:parent,:blck],
331
+ :do=>[],
332
+ :out=>[],
333
+ :blck=>[],
334
+ :saved=>[],
335
+ :call=> [:",",:blck,:"->"],
336
+ :style=> [:of,:",",:blck,:default],
337
+ :input=>[:","],
338
+ :r=>[:in],
339
+ :rverb=>[:in,:mode],
340
+ :rbverb=>[:mode],
341
+ :jlverb=>[:mode],
342
+ :rout=>[:in,:mode],
343
+ :eval=>[:to],
344
+ :ifndef=>[:<<],
345
+ :tags=>[:when],
346
+ :keys=> [],
347
+ :part=>[],
348
+ :get=>[:blck]
349
+ },
350
+ :keyword_reg=>{ #to overpass :keyword
351
+ :new=> '[%.\w,><?=+:-]+',
352
+ :call=> '[%.\w,><?=+:-]+(?:\@|\$)?',
353
+ :style=>'[%.\w,><?=+:-]+',
354
+ :newBlck=>'[%.\w,><?=+:-]+',
355
+ :blckAnyTag=>'[%.\w,><?=+:-]+',
356
+ },
357
+ :with_tagblck =>[:document,:if,:unless,:for,:loop,:case,:set,:def,:meth,:new,:super,:do,:out,:blck,:saved,:call,:style,:rverb,:rbverb,:jlverb,:rout,:tags,:keys,:part],
358
+ :named_tag=>{
359
+ #=begin
360
+ :> => {:tag=>'(_TAG_)(?:[^\]]+)?',:rest=>/^>([^\]]*)$/},
361
+ :>> => {:tag=>'(_TAG_)(?:[^\]]+)?',:rest=>/^>>([^\]]*)$/},
362
+ :"r>" => {:tag=>'(_TAG_)(?:[^\]]+)?',:rest=>/^r>([^\]]*)$/},
363
+ :"rb>" => {:tag=>'(_TAG_)(?:[^\]]+)?',:rest=>/^rb>([^\]]*)$/},
364
+ :"=" => {:tag=>'(_TAG_)(?:[^\]]+)?',:rest=>/^=([^\]]*)$/}
365
+ #=end
366
+ },
367
+ :mode_arg=>:next_block,
368
+ :tag_code=>[:code,:<,:>,:<<,:txt], #used for arg mode!
369
+ :arg=>[:if,:unless,:elsif,:for,:case,:def,:func,:meth,:new,:super,:call,:input,:when,:break,:set,:style,:keys,:"?",:"rb<",:"r<",:"R<",:"m<",:"M<",:"jl<"],
370
+ :blck=>{
371
+ :instr=>[:document,:if,:unless,:case,:loop,:set,:tag,:keys,:rverb,:rbverb,:jlverb,:for],
372
+ :keyword=>{
373
+ :document=>@@tagblck_dyndoc_set + @@tagblck_tex_set + @@tagblck_html_set,
374
+ :set=>[:set],
375
+ :if=>[:if,:unless,:elsif,:else],
376
+ :unless=>[:if,:unless,:elsif,:else],
377
+ :case=>[:when,:else],
378
+ :loop=>[:loop,:break],
379
+ :tags=>[:when],
380
+ :rverb=>[:rverb,:in,:mode],
381
+ :rbverb=>[:rbverb,:mode],
382
+ :jlverb=>[:jlverb,:mode],
383
+ :rout=>[:rout,:in,:mode]
384
+ }
385
+ },
386
+ :style=>"@" #specify that the scanner recognize a style instead a call when blck[:type].include? "@"
387
+ }
388
+ }
389
+
390
+ attr_accessor :dtag
391
+
392
+ def init_tag(type=:dtag)
393
+ @dtag=@@dtag[type]
394
+ @tag_instr=@dtag[:instr]+@dtag[:alias].keys.map{|e| e.to_s}
395
+ @tag_alias=@dtag[:alias]
396
+ @tag_keyword=@dtag[:keyword]
397
+ @tag_keyword_reg=@dtag[:keyword_reg]
398
+ @tag_arg=@dtag[:arg]
399
+ @tag_code=(@dtag[:tag_code] ? @dtag[:tag_code] : [] )
400
+ @tag_style=@dtag[:style]
401
+ @tag_blck=@dtag[:blck]
402
+ ## deal with fixed blck tags
403
+ @named_tags=[]
404
+ @@keystagblck=@@tagblck_set.map{|e| complete_tag(e)}.compact.join("|") #only once!
405
+ @@named_tags_blck=@named_tags
406
+ end
407
+
408
+ def merge_tag(dtag)
409
+ if dtag
410
+ @tag_instr += dtag[:instr] if dtag[:instr]
411
+ @tag_instr += dtag[:alias].keys.map{|e| e.to_s} if dtag[:alias]
412
+ @tag_alias.merge!(dtag[:alias]) if dtag[:alias]
413
+ @tag_keyword.merge!(dtag[:keyword]) if dtag[:keyword]
414
+ @tag_keyword_reg.merge!(dtag[:keyword_reg]) if dtag[:keyword_reg]
415
+ @tag_arg += dtag[:arg] if dtag[:arg]
416
+ if dtag[:blck]
417
+ @tag_blck[:instr] += dtag[:blck][:instr] if dtag[:blck][:instr]
418
+ @tag_blck[:keyword].merge!(dtag[:blck][:keyword]) if dtag[:blck][:keyword]
419
+ end
420
+ end
421
+ end
422
+
423
+ ## update an existing tag keywork (ex: document for html structure by adding #css #js #menu or anything needed in the model)
424
+ def update_tag_keyword(keyword,tags_set=[],args={})
425
+ @tag_keyword[keyword] += tags_set
426
+ @tag_blck[:keyword][keyword] += new_tags_set if args[:mode] && args[:mode] == :blck
427
+ end
428
+
429
+ ## Types of result block:
430
+ ## 1) :main
431
+ ## 2) :args
432
+ ## 3) :instr (:if, :case, ...)
433
+ ## Types of parsed block:
434
+ ## 1) :text -> main block alternating text and dtag blocks
435
+ ## 2) :dtag -> {% ...%}
436
+
437
+ def find_args(inside)
438
+ ## Instruction delimiter
439
+ delim=@block[@scan.pos,1]
440
+ #p delim
441
+ @scan.pos += delim.bytesize #.length
442
+ st=@scan.pos
443
+ delim=@@close[delim] if @@close[delim]
444
+ #p delim
445
+ ## Arguments
446
+ begin
447
+ @scan.scan_until(/#{Regexp.escape(delim)}/)
448
+ end while @block[@scan.pos-2,1]=='\\'
449
+ sp=@scan.pos - delim.bytesize - 1 #.length - 1
450
+ args=@block.byteslice(st..sp) #@block[st..sp]
451
+ inside2=[]
452
+ (1..(args.split(@re_strange,-1).length-1)).each{ inside2 << inside.shift }
453
+ return [:args,{:txt=>args,:inside=>inside2}]
454
+ end
455
+
456
+ def find_text(from,key,inside)
457
+ #p ["key=",key]
458
+ res,to=nil,nil
459
+ pre=(@next_pre ? @next_pre : nil )
460
+ @next_pre=nil
461
+ if @scan[1].nil? or @scan[1].empty? or @is_arg
462
+ #p ["key=",key,@tag_selected]
463
+ if @tag_selected
464
+ @next_pre=key[2...-1].scan(@dtag[:named_tag][@tag_selected.to_sym][:rest])[0][0]
465
+ @next_pre=nil if @next_pre.empty?
466
+ end
467
+ @scan.scan_until(/#{Regexp.escape(key)}/)
468
+ to=@scan.pre_match.bytesize #.length
469
+ ##Dyndoc.warn "TOOOOOOOOOOO",[@scan.pre_match,to]
470
+ res=@block.byteslice(from...to) #@block[from...to]
471
+ else
472
+ #p ["pre_match=",@scan.pre_match,"to=",@scan.pre_match.bytesize]
473
+ to=@scan.pre_match.bytesize #.length
474
+ ##Dyndoc.warn "TOOOOOOOOOOO2222",[@scan.pre_match,to]
475
+ delim2=@scan[1]
476
+ delim2=@@open[delim2] if @@open[delim2]
477
+ #p ["delim2=",delim2,/#{Regexp.escape(delim2)}/]
478
+ #p @block[from...-1]
479
+ @scan.exist?(/#{Regexp.escape(delim2)}/)
480
+ to_tmp=@scan.pre_match.bytesize #.length
481
+ #p ["to_tmp=",to_tmp]
482
+ ## pre=@block[from...to_tmp].strip unless pre
483
+ #p [:pre,pre]
484
+ pre=@block.byteslice(from...to_tmp).strip unless pre
485
+ #p ["pre=",pre]
486
+ from=to_tmp+1
487
+ #p ["key:",key,@scan.matched,from,@block[from-1,1]]
488
+ @scan.scan_until(/#{@tag[:block]}\s*#{Regexp.escape(key)}/)
489
+ =begin
490
+ @scan.scan_until(/[\]|]\s*#{key}/)
491
+ =end
492
+ #p ["matched=",@scan.matched]
493
+ #p @scan.pre_match
494
+ #to=@scan.pre_match.length
495
+ res=@block.byteslice(from...to) #does not work for ruby2 => @block[from...to]
496
+ pre=nil if pre.empty?
497
+ #p ["res=",from,to,res,@block.byteslice(from...to)]
498
+ end
499
+ inside2=[]
500
+ (1..(res.split(@re_strange,-1).length-1)).each{ inside2 << inside.shift }
501
+ return [:text,{:name=>pre,:txt=>res,:inside=>inside2}] if pre
502
+ return [(@is_arg ? :args : :text),{:txt=>res,:inside=>inside2}]
503
+ end
504
+
505
+
506
+ def complete_tag(key,add=true)
507
+ #Regexp.escape(key.to_s)+((@dtag[:named_tag][key]) ? @dtag[:named_tag][key] : "")
508
+ if @dtag[:named_tag][key]
509
+ if add
510
+ @named_tags << key
511
+ return nil
512
+ else
513
+ @dtag[:named_tag][key][:tag].sub("_TAG_",Regexp.escape( key.to_s ))
514
+ end
515
+ else
516
+ return Regexp.escape(key.to_s)
517
+ end
518
+ end
519
+
520
+ def check_until_for_named_tags
521
+ #if res
522
+ @named_tags.each_index{|i|
523
+ if @scan[3+i]
524
+ @tag_selected=@scan[3+i].to_sym
525
+ #puts "here we go: #{@tag_selected}"
526
+ break
527
+ end
528
+ }
529
+ #end
530
+ #return res
531
+ end
532
+
533
+ ## ATTENTION: Ne pas faire de recurrence dans convert_block à cause de @scan! qui est en unique exemplaire!
534
+ def convert_block(blck)
535
+ #puts "split_block";p blck
536
+ @block= blck[:txt]
537
+ inside=blck[:inside]
538
+ style=blck[:type].include? @tag_style
539
+ pre_res=[]
540
+ res=[]
541
+ =begin
542
+ ## Mode -> unused now!
543
+ mode=@block[0,@mode[:length]]
544
+ mode2=(@@close[mode] ? @@close[mode] : mode)
545
+ =end
546
+ @scan.string=@block
547
+ @scan.pos=0
548
+ ## Instruction
549
+ #@scan.scan_until(/(?:#{@tag_instr.join("|")})/)
550
+ @scan.scan_until(@start)
551
+ instr=@scan[1] #@scan.matched
552
+ #p [:instr,instr]
553
+ # next block is a arg block?
554
+ @is_arg=false
555
+ if @tag_instr.include? instr
556
+ instr=instr.to_sym
557
+ instr=@tag_alias[instr] if @tag_alias.include? instr
558
+ if instr.is_a? Array
559
+ res += instr
560
+ instr=instr[0]
561
+ else
562
+ res << instr
563
+ end
564
+ if (@tag_arg+@tag_code).include? instr
565
+ case @dtag[:mode_arg]
566
+ when :find
567
+ res << find_args(inside)
568
+ when :next_block
569
+ @is_arg=true
570
+ end
571
+ end
572
+ else
573
+ instr2=(style ? :style : :call)
574
+ #pour un éventuel ajout de > ou < à la fin
575
+ if [">","<"].include? instr[-1,1]
576
+ instr2,instr=(instr2.to_s+instr[-1,1]).to_sym,instr[0...-1]
577
+ end
578
+ res << instr2 << [:args, {:txt=>instr,:inside=>[]}]
579
+ instr=instr2
580
+ end
581
+ ## Text block
582
+ ## find keywords
583
+ from=true
584
+ #p "todoooo"
585
+ while from
586
+ from=@scan.pos
587
+ #p @tag_keyword[instr]
588
+ #p /(#{@tag[:block]}?)\s*(#{@tag[:keyword][0]}(?:#{keytags=(@tag_keyword[instr] ? @tag_keyword[instr] : [] ).map{|e| Regexp.escape(e.to_s)}.join("|")})#{@dtag[:empty_keyword][0]}#{@tag[:keyword][1]})/
589
+ tag_keyword=nil
590
+ if @dtag[:empty_keyword][0].empty?
591
+ #no empty tag!
592
+ tag_keyword=@tag_keyword[instr] if @tag_keyword[instr]
593
+ else
594
+ tag_keyword=(@tag_keyword[instr] ? @tag_keyword[instr] : [] )
595
+ end
596
+ keytags=nil
597
+ @named_tags,@tag_selected=[],nil
598
+ if tag_keyword
599
+ #p tag_keyword
600
+ if @tag_keyword_reg and @tag_keyword_reg[instr]
601
+ tag_keyword=@tag_keyword_reg[instr]
602
+ blocktag_reg=/(#{@tag[:block]}?)\s*(#{@tag[:keyword][0]}#{tag_keyword}#{@dtag[:empty_keyword][0]}#{@tag[:keyword][1]})/
603
+ tag_reg=/#{tag_keyword}/
604
+ else
605
+ keytags=tag_keyword.map{|e| complete_tag(e)}.compact.join("|")
606
+ #puts "keytags(1)";p keytags
607
+ #puts "INSTR="; p instr
608
+ if @dtag[:with_tagblck].include? instr
609
+ keytags += "|" unless keytags.empty?
610
+ keytags += @@keystagblck
611
+ @named_tags += @@named_tags_blck
612
+ end
613
+ ##puts "keytags(2)";p keytags
614
+ tag_reg=/(?:#{keytags})/
615
+ unless @named_tags.empty?
616
+ keytags += "|"+(@named_tags.map{|tag| complete_tag(tag,nil)}.join("|"))
617
+ end
618
+ ##Dyndoc.warn "keytags",keytags
619
+ blocktag_reg=/(#{@tag[:block]}?)\s*(#{@tag[:keyword][0]}(?:#{keytags})#{@dtag[:empty_keyword][0]}#{@tag[:keyword][1]})/
620
+ end
621
+ ##Dyndoc.warn "to scan", @scan.string[@scan.pos..-1]
622
+ ##Dyndoc.warn "tag_reg",[blocktag_reg,tag_reg]
623
+ end
624
+ if (tag_keyword and (@scan.check_until(blocktag_reg))) #or (!@named_tags.empty? and check_until_for_named_tags)
625
+ check_until_for_named_tags unless @named_tags.empty?
626
+ key=@scan[2]
627
+ ##Dyndoc.warn "keyword",[key,@scan[0],@scan[1],@scan[2]]
628
+ ##Dyndoc.warn "pre_math,tag_selected",[@scan.pre_match,@tag_selected] if key=="[#tag]"
629
+ res << find_text(from,key,inside)
630
+ @is_arg=false if @is_arg
631
+ ##Dyndoc.warn "key(AV)",[key,tag_reg] if key=="[#tag]"
632
+ if @tag_selected
633
+ #puts "tag_selected";p @tag_selected
634
+ res << (key=@tag_selected)
635
+ else
636
+ #key=tag_reg.match(key)[0]
637
+ key= key.scan(tag_reg)[0]
638
+ ##Dyndoc.warn "key(AP)",key if key=="tag"
639
+ res << (key=key.to_sym) if key and !key.empty?
640
+ end
641
+ #res << (key=key[1..-1].to_sym)
642
+ #p @tag_arg
643
+ if @tag_arg.include? key #without @tag_code inside a block
644
+ case @dtag[:mode_arg]
645
+ when :find
646
+ res << find_args(inside)
647
+ from=@scan.pos
648
+ when :next_block
649
+ @is_arg=true
650
+ end
651
+ end
652
+ else
653
+ #Last text block!
654
+ #p /(#{@tag[:block]}?)\s*(#{@tag[:stop]})/
655
+ @scan.check_until(/(#{@tag[:block]}?)\s*(#{@tag[:stop]})/)
656
+ #puts "last"; p @scan[2];p @scan[0]; p @scan[1]
657
+ #p @scan.pre_match
658
+ res << find_text(from,@scan[2],inside)
659
+ #p res
660
+ from=false
661
+ end
662
+ #puts "from2";p from
663
+ end
664
+ #puts "res";p res
665
+ return res
666
+ end
667
+
668
+ def parse_block(blck)
669
+ res=convert_block(blck)
670
+ #puts "res";p res
671
+ ##Stop scan when :txt instruction to avoid parsing!
672
+ if TXT_DTAG.include? res[0]
673
+ res2=[res[0],rebuild_after_filter(res[1][1])]
674
+ # NO MORE POSSIBLE! res2 << res[1][1][:name] if res[1][1][:name]
675
+ #p res2
676
+ return res2
677
+ end
678
+ res2=[]
679
+ res.each{|e|
680
+ #p e
681
+ if e.is_a? Array
682
+ case e[0]
683
+ when :args
684
+ res2 << parse_args(e[1])
685
+ when :text
686
+ res2 += parse_text(e[1])
687
+ end
688
+ else
689
+ res2 << e
690
+ end
691
+ }
692
+ #p res2
693
+ #make :blck block if necessary
694
+ res2=ajust_with_blck(res2)
695
+ #puts "res2";p res2
696
+ return res2
697
+ end
698
+
699
+ def ajust_with_blck(res)
700
+ return res unless @tag_blck[:keyword].include? res[0]
701
+ instr=@tag_blck[:keyword][res[0]]
702
+ res_blck,blck=[],nil
703
+ begin
704
+ b=res.shift
705
+ if instr.include? b
706
+ #create the :blck block
707
+ res_blck << b
708
+ #is there an :args block?
709
+ res_blck << res.shift if @tag_arg.include? b
710
+ #if no first tag_blck then put the default :out tag
711
+ blck=[:blck]
712
+ blck << :out unless @@tagblck_set.include? res[0]
713
+ else
714
+ if blck
715
+ blck << b
716
+ else
717
+ #needed for example :case block
718
+ res_blck << b
719
+ end
720
+ #is the end of blck?
721
+ if res.empty? or (instr.include? res[0])
722
+ res_blck << blck if blck
723
+ blck=nil
724
+ end
725
+ end
726
+ end until res.empty?
727
+ res_blck
728
+ end
729
+
730
+ def parse_args(blck)
731
+ res=[:args]
732
+ #puts ":args";p blck[:txt]
733
+ parts=blck[:txt].split(@re_strange,-1)
734
+ #p parts
735
+ #p blck[:inside]
736
+ blck[:inside].map do |e|
737
+ res << [:main,parts.shift]
738
+ res << parse_block(e)
739
+ end
740
+ res << [:main,parts.shift]
741
+ res
742
+ end
743
+
744
+ def parsed_block_with_modifier(res_block)
745
+ res=nil
746
+ instr=res_block[0,1].to_s
747
+ if !["<","<<",">"].include? instr and [">","<"].include?(modif=instr[-1,1])
748
+ res=modif.to_sym
749
+ res_block[0,1]=instr[0...-1].to_sym
750
+ end
751
+ res
752
+ end
753
+
754
+ def parse_text(blck)
755
+ #puts "blck";p blck
756
+ res=[]
757
+ blck[:txt].split(@re_strange2,-1).each{|e|
758
+ if e==@strange
759
+
760
+ b=blck[:inside].shift
761
+ res_b=parse_block(b)
762
+ if (res_modif=parsed_block_with_modifier(res_b))
763
+ res << res_modif
764
+ end
765
+ #puts "parse_text: res_b";p res_b
766
+ res << res_b
767
+ else
768
+ res << [:main,e]
769
+ end
770
+ }
771
+ res=[[:named,blck[:name]]+res] if blck[:name]
772
+ res
773
+ end
774
+
775
+ def rebuild_after_parse(res)
776
+ txt=""
777
+ start=0
778
+ parts=res[:txt].split(@re_strange,-1)
779
+ res[:inside].map do |e|
780
+ txt << parts.shift
781
+ txt << (e[:inside] ? rebuild_after_parse(e) : e[:txt])
782
+ end
783
+ txt << parts.shift
784
+ txt
785
+ end
786
+
787
+ def process(txt)
788
+ tokenize(txt)
789
+ parse_text(extract)
790
+ end
791
+
792
+ def pretty_print(res,tab=0)
793
+ res.each{|b|
794
+ if b.is_a? Array
795
+ pretty_print(b,tab+1)
796
+ else
797
+ puts " "*tab+b.inspect+"\n"
798
+ end
799
+ }
800
+ end
801
+
802
+ end
803
+
804
+ class VarsScanner < Scanner
805
+
806
+ @@type[:vars]={
807
+ :start=>'<<([\w\@]*)\s*\[',
808
+ :stop=> '\]',
809
+ :mode=>{:start=>-1,:stop=>0,:length=>1}
810
+ }
811
+
812
+ def initialize(type=:vars,start=nil,stop=nil,mode=nil,escape=nil)
813
+ super
814
+ end
815
+
816
+ def make_vars(res)
817
+ vars=[]
818
+ start=0
819
+ parts=res[:txt].split(@re_strange,-1).join("").strip
820
+ #puts "parts";p parts
821
+ #p res
822
+ #puts "inside";p res[:inside]
823
+ res[:inside].map do |e|
824
+ vars2= [e[:type][2..-1].strip,(e[:inside] ? make_vars(e) : e[:txt][(e[:type].bytesize+1)...-1] )] #instead of length
825
+ vars << vars2
826
+ end
827
+ #puts "vars";p vars
828
+ vars
829
+ end
830
+
831
+ def build_dyn_vars(res)
832
+ #puts "res";p res
833
+ is_arr=res.map{|k,v| k}.join("").empty?
834
+ cpt=-1
835
+ res2=[]
836
+ res.each{|k,v|
837
+ #p k;p v
838
+ key2=(k.empty? ? (is_arr ? "" : "key")+(cpt+=1).to_s : k)
839
+ res0=((v.is_a? Array) ? build_dyn_vars(v) : [["",v]])
840
+ #puts "res0";p res0
841
+ res2+=res0.map{|k0,v0| [key2+(k0.empty? ? "" : "." )+k0,v0]}
842
+ #puts "res2";p res2
843
+ }
844
+ #puts "res2";p res2
845
+ res2
846
+ end
847
+
848
+ def build_rb_vars(res)
849
+ #puts "res";p res
850
+ is_arr=res.map{|k,v| k}.join("").empty?
851
+ cpt=0
852
+ res2=(is_arr ? [] : {})
853
+ res.each{|k,v|
854
+ #p k;p v
855
+ v2=((v.is_a? Array) ? build_rb_vars(v) : v)
856
+ if is_arr
857
+ res2 << v2
858
+ else
859
+ key2=(is_arr ? (cpt+=1) : (k.empty? ? "key"+(cpt+=1).to_s : k).to_sym)
860
+ res2[key2]=v2
861
+ end
862
+ }
863
+ #puts "res2";p res2
864
+ res2
865
+ end
866
+
867
+
868
+ def build_vars(txt,type=:dyn)
869
+ #puts "txt";p txt
870
+ return nil unless txt[0,2]=="<<"
871
+ res=tokenize(txt)
872
+ return nil if res[:inside].empty?
873
+ res=make_vars(extract)
874
+ case type
875
+ when :dyn
876
+ #puts "res in build_vars";p res
877
+ build_dyn_vars(res)
878
+ when :rb
879
+ build_rb_vars(res)
880
+ when :r
881
+ end
882
+ end
883
+
884
+
885
+ end
886
+ end