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.
- data/README.txt +36 -0
- data/lib/EFL.rb +494 -0
- data/lib/EFL_array.rb +20 -0
- data/lib/EFL_errors.rb +48 -0
- data/lib/EFL_hash.rb +18 -0
- data/lib/EFL_production.rb +49 -0
- data/lib/EFL_regexp.rb +112 -0
- data/lib/EFL_regexp_generator.rb +70 -0
- data/lib/EFL_substitution.rb +221 -0
- data/lib/EFL_syntactic_sugar.rb +67 -0
- data/lib/Hash Doc.doc +0 -0
- data/lib/Limitaciones.txt +3 -0
- data/lib/doc/classes/Generator.html +634 -0
- data/lib/doc/classes/Generator.src/M000008.html +18 -0
- data/lib/doc/classes/Generator.src/M000009.html +18 -0
- data/lib/doc/classes/Generator.src/M000010.html +18 -0
- data/lib/doc/classes/Generator.src/M000011.html +18 -0
- data/lib/doc/classes/Generator.src/M000012.html +18 -0
- data/lib/doc/classes/Generator.src/M000013.html +18 -0
- data/lib/doc/classes/Generator.src/M000014.html +18 -0
- data/lib/doc/classes/Generator.src/M000015.html +18 -0
- data/lib/doc/classes/Generator.src/M000016.html +28 -0
- data/lib/doc/classes/Generator.src/M000017.html +24 -0
- data/lib/doc/classes/Generator.src/M000018.html +157 -0
- data/lib/doc/classes/Generator.src/M000019.html +25 -0
- data/lib/doc/classes/Generator.src/M000020.html +30 -0
- data/lib/doc/classes/Generator.src/M000021.html +32 -0
- data/lib/doc/classes/Generator.src/M000022.html +22 -0
- data/lib/doc/classes/Generator.src/M000023.html +18 -0
- data/lib/doc/classes/Generator.src/M000024.html +27 -0
- data/lib/doc/classes/Generator.src/M000025.html +22 -0
- data/lib/doc/classes/Generator.src/M000026.html +18 -0
- data/lib/doc/classes/Generator.src/M000027.html +27 -0
- data/lib/doc/classes/Regexp.html +271 -0
- data/lib/doc/classes/Regexp.src/M000028.html +37 -0
- data/lib/doc/classes/Regexp.src/M000029.html +29 -0
- data/lib/doc/classes/Regexp.src/M000030.html +32 -0
- data/lib/doc/created.rid +1 -0
- data/lib/doc/files/EFL_rb.html +147 -0
- data/lib/doc/files/EFL_regexp_generator_rb.html +242 -0
- data/lib/doc/files/EFL_regexp_generator_rb.src/M000003.html +27 -0
- data/lib/doc/files/EFL_regexp_generator_rb.src/M000004.html +27 -0
- data/lib/doc/files/EFL_regexp_generator_rb.src/M000005.html +19 -0
- data/lib/doc/files/EFL_regexp_generator_rb.src/M000006.html +20 -0
- data/lib/doc/files/EFL_regexp_generator_rb.src/M000007.html +19 -0
- data/lib/doc/files/EFL_regexp_rb.html +139 -0
- data/lib/doc/files/EFL_syntactic_sugar_rb.html +208 -0
- data/lib/doc/files/EFL_syntactic_sugar_rb.src/M000001.html +29 -0
- data/lib/doc/files/EFL_syntactic_sugar_rb.src/M000002.html +19 -0
- data/lib/doc/fr_class_index.html +28 -0
- data/lib/doc/fr_file_index.html +30 -0
- data/lib/doc/fr_method_index.html +56 -0
- data/lib/doc/index.html +24 -0
- data/tests/Add_Sup_1.rb +223 -0
- data/tests/Add_Sup_1.rb.bak +223 -0
- data/tests/Add_Sup_1_NI.rb +25 -0
- data/tests/Add_Sup_2.rb +142 -0
- data/tests/Add_Sup_2.rb.bak +140 -0
- data/tests/All.rb +2 -0
- data/tests/All_1.rb +7 -0
- data/tests/All_2.rb +7 -0
- data/tests/All_2.rb.bak +5 -0
- data/tests/BeforeAfter.rb +83 -0
- data/tests/Bloques.rb +34 -0
- data/tests/Bloques.rb.bak +34 -0
- data/tests/Complementary.rb +144 -0
- data/tests/ComplementaryZoom.rb +78 -0
- data/tests/Del.rb +126 -0
- data/tests/Dup.rb +55 -0
- data/tests/Dup.rb.bak +54 -0
- data/tests/Error.rb +11 -0
- data/tests/ErrorArgClass.rb +169 -0
- data/tests/ErrorArgClass.rb.bak +158 -0
- data/tests/ErrorCollision.rb +218 -0
- data/tests/ErrorCollision.rb.bak +219 -0
- data/tests/ErrorWithoutDeclaration.rb +60 -0
- data/tests/ErrorWithoutDeclaration.rb.bak +60 -0
- data/tests/Extract.rb +56 -0
- data/tests/ExtractDollar.rb +17 -0
- data/tests/HashTest.rb +54 -0
- data/tests/HashTest.rb.bak +54 -0
- data/tests/Lista Czarnecki/AntiguaInterfaz/List.cpp +75 -0
- data/tests/Lista Czarnecki/AntiguaInterfaz/ListTransformer.rb +69 -0
- data/tests/Lista Czarnecki/AntiguaInterfaz/ListTransformer.rb.bak +100 -0
- data/tests/Lista Czarnecki/AntiguaInterfaz/ejecutame.bat +1 -0
- data/tests/Lista Czarnecki/AntiguaInterfaz/outDir/MyClassList.cpp +75 -0
- data/tests/Lista Czarnecki/AntiguaInterfaz/runme.bat +1 -0
- data/tests/Lista Czarnecki/AntiguaInterfaz/specification1.txt +5 -0
- data/tests/Lista Czarnecki/AntiguaInterfaz/specification2.txt +3 -0
- data/tests/Lista Czarnecki/AntiguaInterfaz/specification3.txt +5 -0
- data/tests/Lista Czarnecki/NuevaInterfaz/List.cpp +75 -0
- data/tests/Lista Czarnecki/NuevaInterfaz/ListTransformer.rb +58 -0
- data/tests/Lista Czarnecki/NuevaInterfaz/ListTransformer.rb.bak +57 -0
- data/tests/Lista Czarnecki/NuevaInterfaz/ejecutame.bat +1 -0
- data/tests/Lista Czarnecki/NuevaInterfaz/outDir/MyClassList.cpp +75 -0
- data/tests/Lista Czarnecki/NuevaInterfaz/outDir/NewClassList.cpp +75 -0
- data/tests/Lista Czarnecki/NuevaInterfaz/specification1.txt +5 -0
- data/tests/Lista Czarnecki/NuevaInterfaz/specification1.txt.bak +5 -0
- data/tests/Lista Czarnecki/NuevaInterfaz/specification2.txt +3 -0
- data/tests/Lista Czarnecki/NuevaInterfaz/specification3.txt +5 -0
- data/tests/Minus.rb +89 -0
- data/tests/Plus.rb.bak +48 -0
- data/tests/REVit.rb +84 -0
- data/tests/RenameTest.rb +46 -0
- data/tests/RenameTest.rb.bak +46 -0
- data/tests/SubCrash.rb +26 -0
- data/tests/SubList.rb.bak +43 -0
- data/tests/archAuxiliares/1.txt +328 -0
- data/tests/archAuxiliares/2.txt +328 -0
- data/tests/archAuxiliares/Bloques/s1.txt +328 -0
- data/tests/archAuxiliares/Copia de Matriz.java +19 -0
- data/tests/archAuxiliares/Gen/Tesis_156_1.lgi +10 -0
- data/tests/archAuxiliares/Gen/Tesis_156_2.lgi +10 -0
- data/tests/archAuxiliares/Gen/t01.txt +328 -0
- data/tests/archAuxiliares/Gen/t01.txt.bak +328 -0
- data/tests/archAuxiliares/Gen/t02.txt +328 -0
- data/tests/archAuxiliares/Gen/t02.txt.bak +328 -0
- data/tests/archAuxiliares/Gen/t03.txt +328 -0
- data/tests/archAuxiliares/Gen/t03.txt.bak +328 -0
- data/tests/archAuxiliares/Gen/t04.txt +328 -0
- data/tests/archAuxiliares/Gen/t04.txt.bak +328 -0
- data/tests/archAuxiliares/Gen/t1.txt +328 -0
- data/tests/archAuxiliares/Gen/t1.txt.bak +328 -0
- data/tests/archAuxiliares/Gen/t2.txt +328 -0
- data/tests/archAuxiliares/Gen/t2.txt.bak +328 -0
- data/tests/archAuxiliares/Gen/t5.txt +328 -0
- data/tests/archAuxiliares/Gen/t9.txt +328 -0
- data/tests/archAuxiliares/Gen/t9.txt.bak +328 -0
- data/tests/archAuxiliares/GenTesis_156_1.lgi +10 -0
- data/tests/archAuxiliares/Matriz.java +74 -0
- data/tests/archAuxiliares/MatrizOut.java +74 -0
- data/tests/archAuxiliares/MatrizOut10.java +68 -0
- data/tests/archAuxiliares/MatrizOut11.java +86 -0
- data/tests/archAuxiliares/MatrizOut2.java +74 -0
- data/tests/archAuxiliares/MatrizOut3.java +74 -0
- data/tests/archAuxiliares/MatrizOut4.java +74 -0
- data/tests/archAuxiliares/MatrizOut5.java +21 -0
- data/tests/archAuxiliares/MatrizOut6.java +21 -0
- data/tests/archAuxiliares/MatrizOut7.java +21 -0
- data/tests/archAuxiliares/MatrizOut8.java +16 -0
- data/tests/archAuxiliares/MatrizOut9.java +86 -0
- data/tests/archAuxiliares/MatrizOut_9.java +86 -0
- data/tests/archAuxiliares/Matriz_1.java +74 -0
- data/tests/archAuxiliares/Matriz_10.java +68 -0
- data/tests/archAuxiliares/Matriz_11.java +86 -0
- data/tests/archAuxiliares/Matriz_2.java +74 -0
- data/tests/archAuxiliares/Matriz_3.java +74 -0
- data/tests/archAuxiliares/Matriz_4.java +74 -0
- data/tests/archAuxiliares/Matriz_5.java +21 -0
- data/tests/archAuxiliares/Matriz_6.java +21 -0
- data/tests/archAuxiliares/Matriz_7.java +21 -0
- data/tests/archAuxiliares/Matriz_8.java +16 -0
- data/tests/archAuxiliares/Matriz_9.java +86 -0
- data/tests/archAuxiliares/Matriz_N_1.java +21 -0
- data/tests/archAuxiliares/Matriz_N_2.java +91 -0
- data/tests/archAuxiliares/N1.txt +18 -0
- data/tests/archAuxiliares/N1_EXPECTED.txt +18 -0
- data/tests/archAuxiliares/N1_OUT.txt +18 -0
- data/tests/archAuxiliares/N2_EXPECTED.txt +18 -0
- data/tests/archAuxiliares/N2_OUT.txt +18 -0
- data/tests/archAuxiliares/N3.txt +23 -0
- data/tests/archAuxiliares/N3_EXPECTED.txt +22 -0
- data/tests/archAuxiliares/N3_OUT.txt +22 -0
- data/tests/archAuxiliares/N4_EXPECTED.txt +10 -0
- data/tests/archAuxiliares/N4_OUT.txt +10 -0
- data/tests/archAuxiliares/N5_OUT.txt +18 -0
- data/tests/archAuxiliares/N6_OUT.txt +18 -0
- data/tests/archAuxiliares/PedidorTerceroWS.jsp +142 -0
- data/tests/archAuxiliares/Tesis_156.lgi +7 -0
- data/tests/archAuxiliares/aspectgen.rb +328 -0
- data/tests/archAuxiliares/aspectgenCopy.rb +328 -0
- data/tests/archAuxiliares/extract_dollar.txt +1 -0
- data/tests/archAuxiliares/minus.txt +26 -0
- data/tests/archAuxiliares/minus_expected_1.txt +26 -0
- data/tests/archAuxiliares/minus_expected_2.txt +26 -0
- data/tests/archAuxiliares/minus_out_1.txt +26 -0
- data/tests/archAuxiliares/minus_out_2.txt +26 -0
- data/tests/archAuxiliares/p1.txt +328 -0
- data/tests/archAuxiliares/p2.txt +328 -0
- data/tests/archAuxiliares/s1.txt +328 -0
- data/tests/archAuxiliares/s2.txt +328 -0
- data/tests/archAuxiliares/s3.txt +328 -0
- data/tests/archAuxiliares/s4.txt +328 -0
- data/tests/archAuxiliares/s5.txt +328 -0
- data/tests/archAuxiliares/s7.txt +328 -0
- data/tests/archAuxiliares/s8.txt +328 -0
- data/tests/archAuxiliares/s9.txt +328 -0
- data/tests/archAuxiliares/text.txt +1 -0
- data/tests/delay.rb +33 -0
- data/tests/delay.rb.bak +33 -0
- data/tests/satisfy.rb +44 -0
- data/tests/satisfy.rb.bak +34 -0
- metadata +252 -0
data/README.txt
ADDED
|
@@ -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
|
data/lib/EFL.rb
ADDED
|
@@ -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
|
+
|