EFL 1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. data/README.txt +36 -0
  2. data/lib/EFL.rb +494 -0
  3. data/lib/EFL_array.rb +20 -0
  4. data/lib/EFL_errors.rb +48 -0
  5. data/lib/EFL_hash.rb +18 -0
  6. data/lib/EFL_production.rb +49 -0
  7. data/lib/EFL_regexp.rb +112 -0
  8. data/lib/EFL_regexp_generator.rb +70 -0
  9. data/lib/EFL_substitution.rb +221 -0
  10. data/lib/EFL_syntactic_sugar.rb +67 -0
  11. data/lib/Hash Doc.doc +0 -0
  12. data/lib/Limitaciones.txt +3 -0
  13. data/lib/doc/classes/Generator.html +634 -0
  14. data/lib/doc/classes/Generator.src/M000008.html +18 -0
  15. data/lib/doc/classes/Generator.src/M000009.html +18 -0
  16. data/lib/doc/classes/Generator.src/M000010.html +18 -0
  17. data/lib/doc/classes/Generator.src/M000011.html +18 -0
  18. data/lib/doc/classes/Generator.src/M000012.html +18 -0
  19. data/lib/doc/classes/Generator.src/M000013.html +18 -0
  20. data/lib/doc/classes/Generator.src/M000014.html +18 -0
  21. data/lib/doc/classes/Generator.src/M000015.html +18 -0
  22. data/lib/doc/classes/Generator.src/M000016.html +28 -0
  23. data/lib/doc/classes/Generator.src/M000017.html +24 -0
  24. data/lib/doc/classes/Generator.src/M000018.html +157 -0
  25. data/lib/doc/classes/Generator.src/M000019.html +25 -0
  26. data/lib/doc/classes/Generator.src/M000020.html +30 -0
  27. data/lib/doc/classes/Generator.src/M000021.html +32 -0
  28. data/lib/doc/classes/Generator.src/M000022.html +22 -0
  29. data/lib/doc/classes/Generator.src/M000023.html +18 -0
  30. data/lib/doc/classes/Generator.src/M000024.html +27 -0
  31. data/lib/doc/classes/Generator.src/M000025.html +22 -0
  32. data/lib/doc/classes/Generator.src/M000026.html +18 -0
  33. data/lib/doc/classes/Generator.src/M000027.html +27 -0
  34. data/lib/doc/classes/Regexp.html +271 -0
  35. data/lib/doc/classes/Regexp.src/M000028.html +37 -0
  36. data/lib/doc/classes/Regexp.src/M000029.html +29 -0
  37. data/lib/doc/classes/Regexp.src/M000030.html +32 -0
  38. data/lib/doc/created.rid +1 -0
  39. data/lib/doc/files/EFL_rb.html +147 -0
  40. data/lib/doc/files/EFL_regexp_generator_rb.html +242 -0
  41. data/lib/doc/files/EFL_regexp_generator_rb.src/M000003.html +27 -0
  42. data/lib/doc/files/EFL_regexp_generator_rb.src/M000004.html +27 -0
  43. data/lib/doc/files/EFL_regexp_generator_rb.src/M000005.html +19 -0
  44. data/lib/doc/files/EFL_regexp_generator_rb.src/M000006.html +20 -0
  45. data/lib/doc/files/EFL_regexp_generator_rb.src/M000007.html +19 -0
  46. data/lib/doc/files/EFL_regexp_rb.html +139 -0
  47. data/lib/doc/files/EFL_syntactic_sugar_rb.html +208 -0
  48. data/lib/doc/files/EFL_syntactic_sugar_rb.src/M000001.html +29 -0
  49. data/lib/doc/files/EFL_syntactic_sugar_rb.src/M000002.html +19 -0
  50. data/lib/doc/fr_class_index.html +28 -0
  51. data/lib/doc/fr_file_index.html +30 -0
  52. data/lib/doc/fr_method_index.html +56 -0
  53. data/lib/doc/index.html +24 -0
  54. data/tests/Add_Sup_1.rb +223 -0
  55. data/tests/Add_Sup_1.rb.bak +223 -0
  56. data/tests/Add_Sup_1_NI.rb +25 -0
  57. data/tests/Add_Sup_2.rb +142 -0
  58. data/tests/Add_Sup_2.rb.bak +140 -0
  59. data/tests/All.rb +2 -0
  60. data/tests/All_1.rb +7 -0
  61. data/tests/All_2.rb +7 -0
  62. data/tests/All_2.rb.bak +5 -0
  63. data/tests/BeforeAfter.rb +83 -0
  64. data/tests/Bloques.rb +34 -0
  65. data/tests/Bloques.rb.bak +34 -0
  66. data/tests/Complementary.rb +144 -0
  67. data/tests/ComplementaryZoom.rb +78 -0
  68. data/tests/Del.rb +126 -0
  69. data/tests/Dup.rb +55 -0
  70. data/tests/Dup.rb.bak +54 -0
  71. data/tests/Error.rb +11 -0
  72. data/tests/ErrorArgClass.rb +169 -0
  73. data/tests/ErrorArgClass.rb.bak +158 -0
  74. data/tests/ErrorCollision.rb +218 -0
  75. data/tests/ErrorCollision.rb.bak +219 -0
  76. data/tests/ErrorWithoutDeclaration.rb +60 -0
  77. data/tests/ErrorWithoutDeclaration.rb.bak +60 -0
  78. data/tests/Extract.rb +56 -0
  79. data/tests/ExtractDollar.rb +17 -0
  80. data/tests/HashTest.rb +54 -0
  81. data/tests/HashTest.rb.bak +54 -0
  82. data/tests/Lista Czarnecki/AntiguaInterfaz/List.cpp +75 -0
  83. data/tests/Lista Czarnecki/AntiguaInterfaz/ListTransformer.rb +69 -0
  84. data/tests/Lista Czarnecki/AntiguaInterfaz/ListTransformer.rb.bak +100 -0
  85. data/tests/Lista Czarnecki/AntiguaInterfaz/ejecutame.bat +1 -0
  86. data/tests/Lista Czarnecki/AntiguaInterfaz/outDir/MyClassList.cpp +75 -0
  87. data/tests/Lista Czarnecki/AntiguaInterfaz/runme.bat +1 -0
  88. data/tests/Lista Czarnecki/AntiguaInterfaz/specification1.txt +5 -0
  89. data/tests/Lista Czarnecki/AntiguaInterfaz/specification2.txt +3 -0
  90. data/tests/Lista Czarnecki/AntiguaInterfaz/specification3.txt +5 -0
  91. data/tests/Lista Czarnecki/NuevaInterfaz/List.cpp +75 -0
  92. data/tests/Lista Czarnecki/NuevaInterfaz/ListTransformer.rb +58 -0
  93. data/tests/Lista Czarnecki/NuevaInterfaz/ListTransformer.rb.bak +57 -0
  94. data/tests/Lista Czarnecki/NuevaInterfaz/ejecutame.bat +1 -0
  95. data/tests/Lista Czarnecki/NuevaInterfaz/outDir/MyClassList.cpp +75 -0
  96. data/tests/Lista Czarnecki/NuevaInterfaz/outDir/NewClassList.cpp +75 -0
  97. data/tests/Lista Czarnecki/NuevaInterfaz/specification1.txt +5 -0
  98. data/tests/Lista Czarnecki/NuevaInterfaz/specification1.txt.bak +5 -0
  99. data/tests/Lista Czarnecki/NuevaInterfaz/specification2.txt +3 -0
  100. data/tests/Lista Czarnecki/NuevaInterfaz/specification3.txt +5 -0
  101. data/tests/Minus.rb +89 -0
  102. data/tests/Plus.rb.bak +48 -0
  103. data/tests/REVit.rb +84 -0
  104. data/tests/RenameTest.rb +46 -0
  105. data/tests/RenameTest.rb.bak +46 -0
  106. data/tests/SubCrash.rb +26 -0
  107. data/tests/SubList.rb.bak +43 -0
  108. data/tests/archAuxiliares/1.txt +328 -0
  109. data/tests/archAuxiliares/2.txt +328 -0
  110. data/tests/archAuxiliares/Bloques/s1.txt +328 -0
  111. data/tests/archAuxiliares/Copia de Matriz.java +19 -0
  112. data/tests/archAuxiliares/Gen/Tesis_156_1.lgi +10 -0
  113. data/tests/archAuxiliares/Gen/Tesis_156_2.lgi +10 -0
  114. data/tests/archAuxiliares/Gen/t01.txt +328 -0
  115. data/tests/archAuxiliares/Gen/t01.txt.bak +328 -0
  116. data/tests/archAuxiliares/Gen/t02.txt +328 -0
  117. data/tests/archAuxiliares/Gen/t02.txt.bak +328 -0
  118. data/tests/archAuxiliares/Gen/t03.txt +328 -0
  119. data/tests/archAuxiliares/Gen/t03.txt.bak +328 -0
  120. data/tests/archAuxiliares/Gen/t04.txt +328 -0
  121. data/tests/archAuxiliares/Gen/t04.txt.bak +328 -0
  122. data/tests/archAuxiliares/Gen/t1.txt +328 -0
  123. data/tests/archAuxiliares/Gen/t1.txt.bak +328 -0
  124. data/tests/archAuxiliares/Gen/t2.txt +328 -0
  125. data/tests/archAuxiliares/Gen/t2.txt.bak +328 -0
  126. data/tests/archAuxiliares/Gen/t5.txt +328 -0
  127. data/tests/archAuxiliares/Gen/t9.txt +328 -0
  128. data/tests/archAuxiliares/Gen/t9.txt.bak +328 -0
  129. data/tests/archAuxiliares/GenTesis_156_1.lgi +10 -0
  130. data/tests/archAuxiliares/Matriz.java +74 -0
  131. data/tests/archAuxiliares/MatrizOut.java +74 -0
  132. data/tests/archAuxiliares/MatrizOut10.java +68 -0
  133. data/tests/archAuxiliares/MatrizOut11.java +86 -0
  134. data/tests/archAuxiliares/MatrizOut2.java +74 -0
  135. data/tests/archAuxiliares/MatrizOut3.java +74 -0
  136. data/tests/archAuxiliares/MatrizOut4.java +74 -0
  137. data/tests/archAuxiliares/MatrizOut5.java +21 -0
  138. data/tests/archAuxiliares/MatrizOut6.java +21 -0
  139. data/tests/archAuxiliares/MatrizOut7.java +21 -0
  140. data/tests/archAuxiliares/MatrizOut8.java +16 -0
  141. data/tests/archAuxiliares/MatrizOut9.java +86 -0
  142. data/tests/archAuxiliares/MatrizOut_9.java +86 -0
  143. data/tests/archAuxiliares/Matriz_1.java +74 -0
  144. data/tests/archAuxiliares/Matriz_10.java +68 -0
  145. data/tests/archAuxiliares/Matriz_11.java +86 -0
  146. data/tests/archAuxiliares/Matriz_2.java +74 -0
  147. data/tests/archAuxiliares/Matriz_3.java +74 -0
  148. data/tests/archAuxiliares/Matriz_4.java +74 -0
  149. data/tests/archAuxiliares/Matriz_5.java +21 -0
  150. data/tests/archAuxiliares/Matriz_6.java +21 -0
  151. data/tests/archAuxiliares/Matriz_7.java +21 -0
  152. data/tests/archAuxiliares/Matriz_8.java +16 -0
  153. data/tests/archAuxiliares/Matriz_9.java +86 -0
  154. data/tests/archAuxiliares/Matriz_N_1.java +21 -0
  155. data/tests/archAuxiliares/Matriz_N_2.java +91 -0
  156. data/tests/archAuxiliares/N1.txt +18 -0
  157. data/tests/archAuxiliares/N1_EXPECTED.txt +18 -0
  158. data/tests/archAuxiliares/N1_OUT.txt +18 -0
  159. data/tests/archAuxiliares/N2_EXPECTED.txt +18 -0
  160. data/tests/archAuxiliares/N2_OUT.txt +18 -0
  161. data/tests/archAuxiliares/N3.txt +23 -0
  162. data/tests/archAuxiliares/N3_EXPECTED.txt +22 -0
  163. data/tests/archAuxiliares/N3_OUT.txt +22 -0
  164. data/tests/archAuxiliares/N4_EXPECTED.txt +10 -0
  165. data/tests/archAuxiliares/N4_OUT.txt +10 -0
  166. data/tests/archAuxiliares/N5_OUT.txt +18 -0
  167. data/tests/archAuxiliares/N6_OUT.txt +18 -0
  168. data/tests/archAuxiliares/PedidorTerceroWS.jsp +142 -0
  169. data/tests/archAuxiliares/Tesis_156.lgi +7 -0
  170. data/tests/archAuxiliares/aspectgen.rb +328 -0
  171. data/tests/archAuxiliares/aspectgenCopy.rb +328 -0
  172. data/tests/archAuxiliares/extract_dollar.txt +1 -0
  173. data/tests/archAuxiliares/minus.txt +26 -0
  174. data/tests/archAuxiliares/minus_expected_1.txt +26 -0
  175. data/tests/archAuxiliares/minus_expected_2.txt +26 -0
  176. data/tests/archAuxiliares/minus_out_1.txt +26 -0
  177. data/tests/archAuxiliares/minus_out_2.txt +26 -0
  178. data/tests/archAuxiliares/p1.txt +328 -0
  179. data/tests/archAuxiliares/p2.txt +328 -0
  180. data/tests/archAuxiliares/s1.txt +328 -0
  181. data/tests/archAuxiliares/s2.txt +328 -0
  182. data/tests/archAuxiliares/s3.txt +328 -0
  183. data/tests/archAuxiliares/s4.txt +328 -0
  184. data/tests/archAuxiliares/s5.txt +328 -0
  185. data/tests/archAuxiliares/s7.txt +328 -0
  186. data/tests/archAuxiliares/s8.txt +328 -0
  187. data/tests/archAuxiliares/s9.txt +328 -0
  188. data/tests/archAuxiliares/text.txt +1 -0
  189. data/tests/delay.rb +33 -0
  190. data/tests/delay.rb.bak +33 -0
  191. data/tests/satisfy.rb +44 -0
  192. data/tests/satisfy.rb.bak +34 -0
  193. metadata +252 -0
@@ -0,0 +1,36 @@
1
+ Copyright � 2007 by Ruben Heradio Gil, Jose Antonio Cerrada Somolinos, Jose
2
+ Ramon Coz Fernandez and Jose Carlos Lopez Ruiz.
3
+
4
+ This is EFL - A Ruby implementation of the Exemplar Flexibilization Language.
5
+
6
+ EFL is distributed under the terms of the GNU Lesser General Public License
7
+ (LGPL).
8
+
9
+ EFL is free software: you can redistribute it and/or modify it under the terms
10
+ of the GNU Lesser General Public License as published by the Free Software
11
+ Foundation, either version 3 of the License, or (at your option) any later
12
+ version.
13
+
14
+ EFL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
15
+ without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16
+ PURPOSE. See the GNU Lesser General Public License for more details.
17
+
18
+ You should have received a copy of the GNU Lesser General Public License along
19
+ with this program. If not, see <http://www.gnu.org/licenses/>.
20
+
21
+ Contact Information: Ruben Heradio Gil (rheradio@issi.uned.es).
22
+ Phone number: 00 34 91 398 8242, Postal address: Dpto. de Ingenier�a de SW y
23
+ Sistemas Inform�ticos. E.T.S.I. Inform�tica, UNED. C/ Juan del Rosal, 16.
24
+ 28040 Madrid.
25
+
26
+ ===============================================================================
27
+ EFL 1.0 - A Ruby implementation of the Exemplar Flexibilization Language
28
+ ===============================================================================
29
+
30
+ With EFL you can write program generators by analogy (see the Generator class).
31
+ EFL is integrated in the Exemplar Driven Development (EDD) process.
32
+ EDD has been developed by Ruben Heradio to build Software Product Lines (SPLs)
33
+ in a reactive and an extractive way.
34
+ The theoretical basis of EDD and EFL, and a wide variety of examples can be
35
+ found in:
36
+ http://www.issi.uned.es/miembros/pagpersonales/ruben_heradio/rheradio_english.html
@@ -0,0 +1,494 @@
1
+ # :title: EFL 1.0 - A Ruby implementation of the Exemplar Flexibilization Language
2
+ # <em>Copyright � 2007 by Ruben Heradio Gil, Jose Antonio Cerrada Somolinos, Jose Ramon Coz Fernandez and Jose Carlos Lopez Ruiz.</em>
3
+ # <em>This file is part of <b>EFL-A Ruby implementation of the Exemplar Flexibilization Language.</b></em>
4
+ # <em>EFL is distributed under the terms of the GNU Lesser General Public License (LGPL).</em>
5
+ # <em>EFL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.</em>
6
+ # <em>EFL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.</em>
7
+ # <em>You should have received a copy of the GNU Lesser General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.</em>
8
+ # <em>Contact Information: Ruben Heradio Gil (rheradio@issi.uned.es). Phone number: 00 34 91 398 8242, Postal address: Dpto. de Ingenier�a de SW y Sistemas Inform�ticos. E.T.S.I. Inform�tica, UNED. C/ Juan del Rosal, 16. 28040 Madrid.</em>
9
+ #
10
+ # <b>With EFL you can write program generators by analogy (see the Generator class).</b>
11
+ # <b>EFL is integrated in the Exemplar Driven Development (EDD) process.</b>
12
+ # <b>EDD has been developed by Ruben Heradio to build Software Product Lines (SPLs) in a reactive and an extractive way.</b>
13
+ # <b>The theoretical basis of EDD and EFL, and a wide variety of examples can be found in http://www.issi.uned.es/miembros/pagpersonales/ruben_heradio/rheradio_english.html</b>
14
+
15
+ require 'EFL_substitution'
16
+ require 'EFL_production'
17
+ require 'EFL_regexp'
18
+ require 'EFL_hash'
19
+ require 'EFL_array'
20
+ require 'EFL_syntactic_sugar'
21
+ require 'EFL_errors'
22
+ require 'EFL_regexp_generator'
23
+
24
+ #:include: EFL_syntactic_sugar.rb
25
+
26
+ # * Generators are specified using substititions (with the <em>sub</em> and <em>gsub</em> methods), productions (with the <em>prod</em> method) and generations (with the <em>gen</em> method).
27
+ # * Generators can be combined in a sequential orden or mixed using the add (with the + and <em>add</em> methods) and the superposition (with the << and <em>sup!</em> methods).
28
+
29
+ class Generator
30
+
31
+ attr_accessor :sub_hash, :prod_hash #:nodoc:
32
+
33
+
34
+ # Specifies the change of the first occurrence of the pattern expressed by
35
+ # the <tt>reg_exp</tt> regular expression to the <tt>text</tt> string. Optionally,
36
+ # a substitution can be named using the <tt>name</tt> string.
37
+ # To build complex substitution patterns, the regular expressions can be combined
38
+ # using the zoom operator (Regexp#>).
39
+
40
+ def sub(reg_exp, text, name = nil)
41
+ sub_aux(reg_exp, text, name, 'local')
42
+ end #sub
43
+
44
+
45
+ # Specifies a kind of substitution that deletes the first occurrence of the
46
+ # pattern expressed by the <tt>reg_exp</tt> regular expression. Optionally,
47
+ # this substitution can be named using the <tt>name</tt> string.
48
+ # To express complex deletes, the regular expressions can be combined
49
+ # using the zoom operator (Regexp#>).
50
+
51
+ def del(reg_exp, name = nil)
52
+ sub(reg_exp, '', name)
53
+ end #del
54
+
55
+
56
+ # Specifies a kind of substitution that inserts the <tt>text</tt> string
57
+ # before the first occurrence of the pattern expressed by the <tt>reg_exp</tt> regular expression.
58
+ # Optionally, this substitution can be named using the <tt>name</tt> string.
59
+ # To express complex 'before inserts', the regular expressions can be combined
60
+ # using the zoom operator (Regexp#>).
61
+
62
+ def before(reg_exp, text, name = nil)
63
+ sub_aux(reg_exp, text, name, 'before local')
64
+ end #before
65
+
66
+
67
+ # Specifies a kind of substitution that inserts the <tt>text</tt> string
68
+ # after the first occurrence of the pattern expressed by the <tt>reg_exp</tt> regular expression.
69
+ # Optionally, this substitution can be named using the <tt>name</tt> string.
70
+ # To express complex 'after inserts', the regular expressions can be combined
71
+ # using the zoom operator (Regexp#>).
72
+
73
+ def after(reg_exp, text, name = nil)
74
+ sub_aux(reg_exp, text, name, 'after local')
75
+ end #before
76
+
77
+
78
+ # Specifies the change of all the occurrences of the pattern expressed by
79
+ # the <tt>reg_exp</tt> regular expression to the <tt>text</tt> string. Optionally,
80
+ # a substitution can be named using the <tt>name</tt> string.
81
+ # To build complex substitution patterns, the regular expressions can be combined
82
+ # using the zoom operator (Regexp#>).
83
+
84
+ def gsub(reg_exp, text, name = nil)
85
+ sub_aux(reg_exp, text, name, 'global')
86
+ end #gsub
87
+
88
+
89
+ # Specifies a kind of substitution that deletes all the occurrence of the
90
+ # pattern expressed by the <tt>reg_exp</tt> regular expression. Optionally,
91
+ # this substitution can be named using the <tt>name</tt> string.
92
+ # To express complex deletes, the regular expressions can be combined
93
+ # using the zoom operator (Regexp#>).
94
+
95
+ def gdel(reg_exp, name = nil)
96
+ gsub(reg_exp, '', name)
97
+ end #del
98
+
99
+
100
+ # Specifies a kind of substitution that inserts the <tt>text</tt> string
101
+ # before all the occurrences of the pattern expressed by the <tt>reg_exp</tt> regular expression.
102
+ # Optionally, this substitution can be named using the <tt>name</tt> string.
103
+ # To express complex 'global before inserts', the regular expressions can be combined
104
+ # using the zoom operator (Regexp#>).def gbefore(reg_exp, text, name = nil)
105
+
106
+ def gbefore(reg_exp, text, name = nil)
107
+ sub_aux(reg_exp, text, name, 'before global')
108
+ end #gbefore
109
+
110
+ # Specifies a kind of substitution that inserts the <tt>text</tt> string
111
+ # after all the occurrences of the pattern expressed by the <tt>reg_exp</tt> regular expression.
112
+ # Optionally, this substitution can be named using the <tt>name</tt> string.
113
+ # To express complex 'global after inserts', the regular expressions can be combined
114
+ # using the zoom operator (Regexp#>).def gbefore(reg_exp, text, name = nil)
115
+
116
+ def gafter(reg_exp, text, name = nil)
117
+ sub_aux(reg_exp, text, name, 'after global')
118
+ end #before
119
+
120
+ def ensure_sub(reg_exp, text, name) #:nodoc:
121
+ if text.kind_of?(String)
122
+ eval Error.arg_class(['reg_exp', 'Regexp'],
123
+ ['text', 'String'],
124
+ ['name', 'String'])
125
+ else #text.kind_of?(String)
126
+ eval Error.arg_class(['reg_exp', 'Regexp'],
127
+ ['text', 'Array'],
128
+ ['name', 'String'])
129
+ end
130
+ end #ensure_sub
131
+
132
+ def sub_aux(reg_exp, text, name, scope) #:nodoc:
133
+ ensure_sub(reg_exp, text, name)
134
+ @sub_hash = {} unless @sub_hash
135
+ name = 'anonymous_' + @sub_hash.length.to_s unless name
136
+ if text.kind_of?(String)
137
+ @sub_hash[name] = Substitution.new(reg_exp, text, scope)
138
+ else #text.kind_of?(Array)
139
+ @sub_hash[name] = Substitution.new(reg_exp, text.join("\n"), scope)
140
+ end
141
+ end #sub_aux
142
+
143
+
144
+ # Specifies the application of a set of substitutions (<tt>sub_list</tt>) on an input file (<tt>i_file</tt>) to produce an output file (<tt>o_file</tt>).
145
+ # * Optionally, a production can be named using the <tt>name</tt> string.
146
+ # * If <tt>sub_list</tt> is not specified, it will contain implicitly all the substitutions defined before the current production.
147
+ # * The order of the substitutions in <tt>sub_list</tt> is irrelevant.
148
+ # * It is posible that several substitutions of <tt>sub_list</tt> try to make different changes over the same area of the exemplar. This kind of collisions will be detected automatically calling the method <tt>prod?</tt> (internally, <tt>prod</tt> calls <tt>prod?</tt>).
149
+
150
+ def prod(i_file, o_file, sub_list = nil, name = nil)
151
+ @sub_hash = {} unless @sub_hash
152
+ @prod_hash = {} unless @prod_hash
153
+ sub_list = @sub_hash.keys if !sub_list or sub_list == 'all'
154
+ name = 'anonymous_' + @prod_hash.length.to_s unless name
155
+ eval Error.arg_class(['i_file', 'String'],
156
+ ['o_file', 'String'],
157
+ ['sub_list', 'Array'],
158
+ ['name', 'String'])
159
+ eval Error.without_declaration('sub')
160
+ eval Error.collision('prod')
161
+ @prod_hash[name] = Production.new(i_file, o_file, sub_list)
162
+ end #prod
163
+
164
+
165
+ # Returns if it is possible to execute a production (see <tt>prod</tt>)
166
+
167
+ def prod?(i_file, o_file, sub_list = nil)
168
+ @sub_hash = {} unless @sub_hash
169
+ sub_list = @sub_hash.keys if !sub_list or sub_list == 'all'
170
+ eval Error.arg_class(['i_file', 'String'],
171
+ ['o_file', 'String'],
172
+ ['sub_list', 'Array'])
173
+ eval Error.without_declaration('sub')
174
+ return !Production.new(i_file, o_file, sub_list).crash?(@sub_hash)
175
+ end #prod?
176
+
177
+
178
+ # Specifies the execution of the set of productions <tt>prod_list</tt>.
179
+ # * If <tt>prod_list</tt> is not specified, it will contain implicitly all the productions defined before the current generation.
180
+ # * The order of the productions in <tt>prod_list</tt> is irrelevant.
181
+ # * It is posible that several substitutions included in the productions of <tt>sub_list</tt> try to make different changes over the same area of the exemplar. This kind of collisions will be detected automatically calling the method <tt>gen?</tt> (internally, <tt>gen</tt> calls <tt>gen?</tt>).
182
+
183
+ def gen(prod_list = nil)
184
+
185
+ #####################################################
186
+ # <gen auxiliar methods>
187
+ #####################################################
188
+
189
+ def mixGen(prod_list) #:nodoc:
190
+ return prod_list, @prod_hash.dup if prod_list.length == 1
191
+ mixedList = []
192
+ prod_hashMixed = @prod_hash.dup
193
+ 0.upto(prod_list.length-2) {|i|
194
+ if !mixedList.include?(prod_list.at(i))
195
+ (i+1).upto(prod_list.length-1) {|j|
196
+ if !mixedList.include?(prod_list.at(j))
197
+ if prod_hashMixed[prod_list.at(i)].o_file ==
198
+ @prod_hash[prod_list.at(j)].o_file
199
+ mixedList.push(prod_list.at(j))
200
+ prod_hashMixed[prod_list.at(i)].sub_list +=
201
+ @prod_hash[prod_list.at(j)].sub_list
202
+ prod_hashMixed.delete(prod_list.at(j))
203
+ end
204
+ end #if
205
+ } #j
206
+ end #if
207
+ } #i
208
+ return prod_list-mixedList, prod_hashMixed
209
+ end #mixGen
210
+
211
+ def replace(source_str, replace_list) #:nodoc:
212
+ delta_length = 0
213
+ result_str = source_str.dup
214
+ replace_list.each { |rep|
215
+ str1 = result_str[0, rep[0] + delta_length]
216
+ str2 = result_str[rep[0] + delta_length, rep[1] - rep[0] +1]
217
+ str3 = result_str[rep[1] + 1 + delta_length, result_str.length - 1]
218
+ str2 =~ @sub_hash[rep[2]].reg_exp.zoom_list.last
219
+ str = ''
220
+ eval("str = " + '"' + @sub_hash[rep[2]].text + '"')
221
+ result_str = str1 + str + str3
222
+ delta_length = result_str.length - source_str.length
223
+ }
224
+ return result_str
225
+ end
226
+
227
+ def mix_subs(sub_list, i_file) #:nodoc:
228
+ result = []
229
+ sub_list.each { |s|
230
+ # local substitutions
231
+ if /local/ =~ @sub_hash[s].scope then
232
+ if /before/ =~ @sub_hash[s].scope then
233
+ element = @sub_hash[s].match_hash[i_file][0].dup
234
+ element[1] = element[0] - 1
235
+ element << s
236
+ result << element
237
+ elsif /after/ =~ @sub_hash[s].scope then
238
+ element = @sub_hash[s].match_hash[i_file][0].dup
239
+ element[0] = element[1] + 1
240
+ element << s
241
+ result << element
242
+ else
243
+ element = @sub_hash[s].match_hash[i_file][0].dup
244
+ element << s
245
+ result << element
246
+ end
247
+ # global substitutions
248
+ else
249
+ if /before/ =~ @sub_hash[s].scope then
250
+ @sub_hash[s].match_hash[i_file].each { |m|
251
+ element = m.dup
252
+ element[1] = element[0] - 1
253
+ element << s
254
+ result << element
255
+ }
256
+ elsif /after/ =~ @sub_hash[s].scope then
257
+ @sub_hash[s].match_hash[i_file].each { |m|
258
+ element = m.dup
259
+ element[0] = element[1] + 1
260
+ element << s
261
+ result << element
262
+ }
263
+ else
264
+ @sub_hash[s].match_hash[i_file].each { |m|
265
+ element = m.dup
266
+ element << s
267
+ result << element
268
+ }
269
+ end
270
+ end
271
+ }
272
+ result.sort! { |e1, e2|
273
+ if e1[0] == e2[0] then
274
+ e1[1] <=> e2[1]
275
+ else
276
+ e1[0] <=> e2[0]
277
+ end
278
+ }
279
+ return result
280
+ end
281
+
282
+ #####################################################
283
+ # </gen auxiliar methods>
284
+ #####################################################
285
+
286
+ @sub_hash = {} unless @sub_hash
287
+ @prod_hash = {} unless @prod_hash
288
+ prod_list = @prod_hash.keys if !prod_list or prod_list == 'all'
289
+
290
+ eval Error.arg_class(['prod_list', 'Array'])
291
+ eval Error.without_declaration('prod')
292
+ eval Error.collision('gen')
293
+ prod_listM, prod_hashM = mixGen(prod_list)
294
+
295
+ prod_listM.each { |p|
296
+ File.open(prod_hashM[p].i_file) {|f|
297
+ exemplar_code = f.read
298
+
299
+ # force the match of every substitution
300
+ prod_hashM[p].sub_list.each {|s|
301
+ if !@sub_hash[s].match_hash[prod_hashM[p].i_file] then
302
+ @sub_hash[s].match_hash[prod_hashM[p].i_file] = @sub_hash[s].get_match_pos(exemplar_code, @sub_hash[s].reg_exp, @sub_hash[s].scope)
303
+ end
304
+ }
305
+
306
+ exemplar_code = replace( exemplar_code, mix_subs(prod_hashM[p].sub_list, prod_hashM[p].i_file) )
307
+
308
+ o_dir = File.dirname(prod_hashM[p].o_file)
309
+ begin
310
+ Dir.mkdir(o_dir) unless FileTest.exist?(o_dir)
311
+ rescue
312
+ if !FileTest.exist?(o_dir) then
313
+ operating_system_command = "`mkdir #{o_dir.gsub(/\\/, '\\\\\\')}`"
314
+ eval operating_system_command
315
+ end
316
+ end
317
+
318
+ File.open(prod_hashM[p].o_file, "w+") {|o_file|
319
+ o_file.write(exemplar_code)
320
+ } #File.open(prod_hashM[p].o_file, "w+")
321
+ } #File.open(prod_hashM[p].i_file)
322
+ } #@prod_listM.each
323
+
324
+ end #gen
325
+
326
+
327
+ # Returns if it is possible to execute a generation (see <tt>gen</tt>)
328
+
329
+ def gen?(prod_list = nil)
330
+ @sub_hash = {} unless @sub_hash
331
+ @prod_hash = {} unless @prod_hash
332
+ prod_list = @prod_hash.keys if !prod_list or prod_list == 'all'
333
+ eval Error.arg_class(['prod_list', 'Array'])
334
+ eval Error.without_declaration('prod')
335
+ !prod_list.oneOnRest {|p1, p2|
336
+ @prod_hash[p1].crash?(@sub_hash, @prod_hash[p2])
337
+ }
338
+ end #gen?
339
+
340
+
341
+ # Returns an array of the strings resulted on matching the <tt>reg_exp</tt> regular expression on
342
+ # the input file <tt>file</tt>
343
+
344
+ def extract(file, reg_exp)
345
+ eval Error.arg_class(['file', 'String'], ['reg_exp', 'Regexp'])
346
+ result = []
347
+ file_code = ''
348
+ pos = []
349
+ File.open(file) {|file|
350
+ file_code = file.read
351
+ s = Substitution.new(//,'','global')
352
+ pos = s.get_match_pos(file_code, reg_exp, s.scope)
353
+ }
354
+ pos.each { |p|
355
+ result << file_code[p[0], p[1] - p[0] + 1]
356
+ }
357
+ return result
358
+ end
359
+
360
+
361
+ # Returns an array of the strings grouped by the parenthesis <tt>number</tt> when the <tt>reg_exp</tt> regular expression is matched on
362
+ # the input <tt>file</tt>.
363
+ #
364
+ # For example. if the content of <tt>myfile.txt</tt> is:
365
+ #
366
+ # <tt>This is my code</tt>
367
+ #
368
+ # The result of execute:
369
+ #
370
+ # <tt>g = generator</tt>
371
+ #
372
+ # <tt>puts "$1 = " + g.extract_dollar('myfile.txt', /(This).*?(code).*?/, 1).to_s</tt>
373
+ #
374
+ # <tt>puts "$2 = " + g.extract_dollar('myfile.txt', /(This).*?(code).*?/, 2).to_s</tt>
375
+ #
376
+ # would be
377
+ #
378
+ # <tt>$1 = This</tt>
379
+ #
380
+ # <tt>$2 = code</tt>
381
+
382
+ def extract_dollar(file, reg_exp, number)
383
+ eval Error.arg_class(['file', 'String'], ['reg_exp', 'Regexp'], ['number', 'Integer'])
384
+
385
+ result = []
386
+ file_code = ''
387
+ pos = []
388
+ File.open(file) {|file|
389
+ file_code = file.read
390
+ s = Substitution.new(//,'','global')
391
+ pos = s.get_match_pos(file_code, reg_exp, s.scope)
392
+ }
393
+ pos.each { |p|
394
+ file_code[p[0], p[1] - p[0] + 1] =~ reg_exp.zoom_list.last
395
+ eval "result << $#{number}"
396
+ }
397
+ return result
398
+ end
399
+
400
+
401
+ def rename #:nodoc:
402
+ result = Generator.new
403
+ result.sub_hash = @sub_hash.my_collect { |key, value|
404
+ ["#{key}__#{self.class}: #{self.object_id}", value]
405
+ }
406
+ result.prod_hash = @prod_hash.my_collect { |key, value|
407
+ key = "#{key}__#{self.class}: #{self.object_id}"
408
+ value.sub_list.collect! {|element|
409
+ "#{element}__#{self.class}: #{self.object_id}"
410
+ }
411
+ [key, value]
412
+ }
413
+ return result
414
+ end #rename
415
+
416
+
417
+ # Adds <tt>self</tt> and <tt>generator</tt>. Returns a new Generator which substitutions and productions are the union
418
+ # of the substitutions and the productions of <tt>self</tt> and <tt>generator</tt>.
419
+ # Collisions between the substitutions of <tt>self</tt> and <tt>generator</tt> will be detected automatically calling the method <tt>add?</tt> (internally, + calls <tt>add?</tt>)
420
+
421
+ def +(generator)
422
+ eval Error.arg_class(['generator', 'Generator'])
423
+ eval Error.collision('add')
424
+ gen1 = rename
425
+ gen2 = generator.rename
426
+ return gen1 << gen2
427
+ end #+
428
+
429
+
430
+ # Prefix notation for +
431
+
432
+ def add(generator)
433
+ self + generator
434
+ end #add
435
+
436
+
437
+ # Returns if it is possible to add <tt>self</tt> and <tt>generator</tt> (see + and <tt>add</tt>)
438
+
439
+ def add?(generator)
440
+ eval Error.arg_class(['generator', 'Generator'])
441
+ gen1 = rename
442
+ gen2 = generator.rename
443
+ gen1.sub_hash.update(gen2.sub_hash)
444
+ gen1.prod_hash.each_value {|p1|
445
+ gen2.prod_hash.each_value {|p2|
446
+ return false if p1.crash?(gen1.sub_hash, p2)
447
+ } #prod_hash2
448
+ } #prod_hash1
449
+ return true
450
+ end #add?
451
+
452
+
453
+ # Superpose <tt>generator</tt> to <tt>self</tt>. << actualizes the substitutions and productions of <tt>self</tt> with the substitutions and productions of <tt>generator</tt>.
454
+ # The substitutions and productions of <tt>generator</tt> with a common name in <tt>self</tt> are overwritten in <tt>self</tt>.
455
+ # The others are added to <tt>self</tt>.
456
+ # Collisions between the substitutions of <tt>self</tt> and <tt>generator</tt> will be detected automatically calling the method <tt>sup</tt> (internally, << calls <tt>sup?</tt>)
457
+
458
+ def <<(generator)
459
+ eval Error.arg_class(['generator', 'Generator'])
460
+ eval Error.collision('sup')
461
+ @sub_hash.update(generator.sub_hash)
462
+ @prod_hash.update(generator.prod_hash)
463
+ return self
464
+ end #<<
465
+
466
+
467
+ # Prefix notation for <<
468
+
469
+ def sup!(generator)
470
+ self << generator
471
+ end #sup!
472
+
473
+
474
+ # Returns if it is possible to superpose <tt>self</tt> to <tt>generator</tt> (see << and <tt>sup!</tt>)
475
+
476
+ def sup?(generator)
477
+ eval Error.arg_class(['generator', 'Generator'])
478
+ sub_hashAux = @sub_hash.dup.update(generator.sub_hash)
479
+ generator.prod_hash.each { |k1, v1|
480
+ @prod_hash.each { |k2, v2|
481
+ if (k1 != k2) && (v1.crash?(sub_hashAux, v2))
482
+ return false
483
+ end
484
+ }
485
+ }
486
+ return true
487
+ end #sup?
488
+
489
+
490
+ public :sub, :del, :before, :after, :gsub, :gdel, :gbefore, :gafter, :prod, :prod?, :gen, :gen?, :extract, :extract_dollar, :+, :add, :add?, :<<, :sup!, :sup?
491
+ protected :sub_aux, :ensure_sub, :rename
492
+
493
+ end #Generator
494
+