SEATC 0.0.1 → 0.0.4
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.
- checksums.yaml +5 -5
- data/lib/Finite Automaton Analyzer.rb +4 -102
- data/lib/Regular Expression.rb +32 -0
- data/lib/Regular Grammar Analyzer.rb +180 -0
- data/samples/Regular Expression.jff +5 -0
- data/samples/Regular Grammar.jff +16 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 66f327a45f65437e97b2156761a3b883888a6b94
|
4
|
+
data.tar.gz: 6f0cf8d8a198887c54fb4f91517ab0978875db27
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f9a3893997079096c785eae03bb4d9603a85213127829083fac635a7425fab0e1c4a05dba6b52ee5fa2c95f42967914a583a8dbe980721b751328d835ca53dea
|
7
|
+
data.tar.gz: 772c965d67357ed2259d15bf0c1c6ac61ca9e2a1c7f3b6ec8d501aed254576e3cad9ff9eb5f03bce83206d31b8dcda6ce9248ad2bb098bb64cd1cfb6bacce91c
|
@@ -9,9 +9,6 @@ class State
|
|
9
9
|
@transitions = Hash.new
|
10
10
|
@final = final
|
11
11
|
end
|
12
|
-
def print()
|
13
|
-
puts "My ID is #{@id} and I am #{@nombre}"
|
14
|
-
end
|
15
12
|
def addTrans(char, to)
|
16
13
|
@transitions[char] = to
|
17
14
|
end
|
@@ -76,7 +73,6 @@ class FiniteAutomatonAnalyzer
|
|
76
73
|
break
|
77
74
|
end
|
78
75
|
end
|
79
|
-
puts "Ending line is #{line}"
|
80
76
|
if(brokenLoop)
|
81
77
|
ret = false
|
82
78
|
else
|
@@ -88,89 +84,6 @@ class FiniteAutomatonAnalyzer
|
|
88
84
|
end
|
89
85
|
end
|
90
86
|
|
91
|
-
#Returns true if the automaton ends in final state, returns false otherwise
|
92
|
-
def self.analizeFiniteAutomatonFromFile(sourceFile, testFile)
|
93
|
-
file = File.new(sourceFile, "r")
|
94
|
-
line = file.read
|
95
|
-
file.close
|
96
|
-
counter = 1
|
97
|
-
lines = line.split("\n")
|
98
|
-
for lin in lines
|
99
|
-
puts "#{counter}: #{lin}"
|
100
|
-
counter = counter + 1
|
101
|
-
end
|
102
|
-
if lines[0] != "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><!--Created with JFLAP 6.4.--><structure> "
|
103
|
-
puts "Not a JFLAP file"
|
104
|
-
end
|
105
|
-
# Check if finite automaton
|
106
|
-
puts lines[1]
|
107
|
-
if lines[1] == "\t<type>fa</type> "
|
108
|
-
puts "Finite automaton"
|
109
|
-
else
|
110
|
-
puts "Not a finite automaton"
|
111
|
-
end
|
112
|
-
states = []
|
113
|
-
counter = 4
|
114
|
-
i = 0
|
115
|
-
initialState = nil
|
116
|
-
modified = lines[counter]
|
117
|
-
while(modified.include? "state")
|
118
|
-
final = 0
|
119
|
-
aux = counter
|
120
|
-
id = getStateID(modified)
|
121
|
-
nombre = getStateName(modified)
|
122
|
-
puts "Modified string for state is ", modified
|
123
|
-
puts id
|
124
|
-
puts nombre
|
125
|
-
if(lines[counter + 3 ].include? "initial")
|
126
|
-
aux = aux + 1
|
127
|
-
initialState = id
|
128
|
-
end
|
129
|
-
if(lines[aux + 3].include? "final")
|
130
|
-
final = 1
|
131
|
-
aux = aux + 1
|
132
|
-
end
|
133
|
-
counter = aux + 4
|
134
|
-
modified = lines[counter]
|
135
|
-
states[id] = State.new(id, nombre, final)
|
136
|
-
i = i + 1
|
137
|
-
end
|
138
|
-
counter = counter + 1
|
139
|
-
modified = lines[counter]
|
140
|
-
puts states[5]==nil
|
141
|
-
while(modified.include? "transition")
|
142
|
-
counter = counter + 1
|
143
|
-
modified = lines[counter]
|
144
|
-
modified.slice! "\t\t\t<from>"
|
145
|
-
from = readTransInt(modified)
|
146
|
-
counter = counter + 1
|
147
|
-
modified = lines[counter]
|
148
|
-
modified.slice! "\t\t\t<to>"
|
149
|
-
to = readTransInt(modified)
|
150
|
-
counter = counter + 1
|
151
|
-
modified = lines[counter]
|
152
|
-
modified.slice! "\t\t\t<read>"
|
153
|
-
trans = modified[0]
|
154
|
-
states[from].addTrans(trans, to)
|
155
|
-
counter = counter + 2
|
156
|
-
modified = lines[counter]
|
157
|
-
puts "Lets go from #{from} to #{to} with #{trans}"
|
158
|
-
end
|
159
|
-
puts "Initial state is #{initialState}"
|
160
|
-
|
161
|
-
#Validate
|
162
|
-
file = File.new(testFile, "r")
|
163
|
-
line = file.read
|
164
|
-
file.close
|
165
|
-
counter = 1
|
166
|
-
lines = line.split("\n")
|
167
|
-
for lin in lines
|
168
|
-
puts "#{counter}: #{lin}"
|
169
|
-
valid = validateString(initialState, states, lin)
|
170
|
-
puts "Is valid? #{valid}"
|
171
|
-
counter = counter + 1
|
172
|
-
end
|
173
|
-
end
|
174
87
|
#Returns true if the automaton ends in final state, returns false otherwise
|
175
88
|
def self.analizeFiniteAutomatonFromString(sourceFile, testString)
|
176
89
|
file = File.new(sourceFile, "r")
|
@@ -179,19 +92,14 @@ class FiniteAutomatonAnalyzer
|
|
179
92
|
counter = 1
|
180
93
|
lines = line.split("\n")
|
181
94
|
for lin in lines
|
182
|
-
puts "#{counter}: #{lin}"
|
183
95
|
counter = counter + 1
|
184
96
|
end
|
185
|
-
|
186
|
-
|
187
|
-
puts "Not a JFLAP file"
|
97
|
+
if !lines[0].match? "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"
|
98
|
+
return false
|
188
99
|
end
|
189
100
|
# Check if finite automaton
|
190
|
-
|
191
|
-
|
192
|
-
puts "Finite automaton"
|
193
|
-
else
|
194
|
-
puts "Not a finite automaton"
|
101
|
+
if !lines[1].include? "<type>fa</type> "
|
102
|
+
return false
|
195
103
|
end
|
196
104
|
states = []
|
197
105
|
counter = 4
|
@@ -203,9 +111,6 @@ class FiniteAutomatonAnalyzer
|
|
203
111
|
aux = counter
|
204
112
|
id = getStateID(modified)
|
205
113
|
nombre = getStateName(modified)
|
206
|
-
puts "Modified string for state is ", modified
|
207
|
-
puts id
|
208
|
-
puts nombre
|
209
114
|
if(lines[counter + 3 ].include? "initial")
|
210
115
|
aux = aux + 1
|
211
116
|
initialState = id
|
@@ -221,7 +126,6 @@ class FiniteAutomatonAnalyzer
|
|
221
126
|
end
|
222
127
|
counter = counter + 1
|
223
128
|
modified = lines[counter]
|
224
|
-
puts states[5]==nil
|
225
129
|
while(modified.include? "transition")
|
226
130
|
counter = counter + 1
|
227
131
|
modified = lines[counter]
|
@@ -238,9 +142,7 @@ class FiniteAutomatonAnalyzer
|
|
238
142
|
states[from].addTrans(trans, to)
|
239
143
|
counter = counter + 2
|
240
144
|
modified = lines[counter]
|
241
|
-
puts "Lets go from #{from} to #{to} with #{trans}"
|
242
145
|
end
|
243
|
-
puts "Initial state is #{initialState}"
|
244
146
|
|
245
147
|
#Validate
|
246
148
|
lin = testString
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class RegularExpression
|
2
|
+
@regex
|
3
|
+
|
4
|
+
def readFile(file)
|
5
|
+
file = File.new(file, "r")
|
6
|
+
line = file.read
|
7
|
+
file.close
|
8
|
+
lines = line.split("\n")
|
9
|
+
end
|
10
|
+
|
11
|
+
def createRegex(lines)
|
12
|
+
regex = ""
|
13
|
+
if !lines[0].match "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"
|
14
|
+
end
|
15
|
+
if !lines[1].include? "\t<type>re</type>"
|
16
|
+
end
|
17
|
+
regex = lines[3]
|
18
|
+
regex.slice! "\t<expression>"
|
19
|
+
regex.reverse!
|
20
|
+
regex.slice! "</expression>".reverse
|
21
|
+
regex.reverse!
|
22
|
+
@regex = Regexp.new regex
|
23
|
+
end
|
24
|
+
def analyze(file, input)
|
25
|
+
createRegex(readFile(file))
|
26
|
+
if @regex.match(input)
|
27
|
+
return true
|
28
|
+
else
|
29
|
+
return false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
class RegularGrammarProduction
|
2
|
+
@left
|
3
|
+
@right
|
4
|
+
def initialize(left)
|
5
|
+
@left = left
|
6
|
+
@right = []
|
7
|
+
end
|
8
|
+
def addRight(right)
|
9
|
+
@right.push(right)
|
10
|
+
end
|
11
|
+
def getRight()
|
12
|
+
return @right
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
SYNTAX_ERROR = 1
|
17
|
+
PRODUCTION_ERROR = 2
|
18
|
+
|
19
|
+
class RegularGrammar
|
20
|
+
@valid
|
21
|
+
@error
|
22
|
+
|
23
|
+
def initialize()
|
24
|
+
@valid = false
|
25
|
+
@error = 0
|
26
|
+
end
|
27
|
+
def getLeft(modified)
|
28
|
+
modified.slice! "\t\t<left>"
|
29
|
+
ret = modified[0]
|
30
|
+
end
|
31
|
+
|
32
|
+
def getRight(modified)
|
33
|
+
modified.slice! "\t\t<right>"
|
34
|
+
ret = ""
|
35
|
+
while(modified[0] != "<")
|
36
|
+
sliced = modified[0]
|
37
|
+
modified.slice! sliced
|
38
|
+
ret = ret + sliced
|
39
|
+
end
|
40
|
+
return ret
|
41
|
+
end
|
42
|
+
|
43
|
+
#returns an Array containing the lines from the file
|
44
|
+
def readFile(file)
|
45
|
+
file = File.new(file, "r")
|
46
|
+
line = file.read
|
47
|
+
file.close
|
48
|
+
lines = line.split("\n")
|
49
|
+
end
|
50
|
+
|
51
|
+
#returns the Hash containing the productions
|
52
|
+
def createProductions(lines)
|
53
|
+
productions = Hash.new
|
54
|
+
if !lines[0].include? "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><!--Created with JFLAP 6.4.--><structure> "
|
55
|
+
@error = SYNTAX_ERROR
|
56
|
+
return productions
|
57
|
+
end
|
58
|
+
if !lines[1].include? "\t<type>grammar</type> "
|
59
|
+
@error = SYNTAX_ERROR
|
60
|
+
return productions
|
61
|
+
end
|
62
|
+
counter = 3
|
63
|
+
i = 0
|
64
|
+
modified = lines[counter]
|
65
|
+
while(modified.include? "production")
|
66
|
+
modified = lines[counter + 1]
|
67
|
+
left = getLeft(modified)
|
68
|
+
modified = lines[counter + 2]
|
69
|
+
right = getRight(modified)
|
70
|
+
while right[0] == "\t"
|
71
|
+
right.slice! "\t"
|
72
|
+
end
|
73
|
+
if right.length > 2
|
74
|
+
@error = PRODUCTION_ERROR
|
75
|
+
end
|
76
|
+
counter = counter + 4
|
77
|
+
modified = lines[counter]
|
78
|
+
if productions[left] == nil
|
79
|
+
productions[left] = RegularGrammarProduction.new(left)
|
80
|
+
end
|
81
|
+
productions[left].addRight(right)
|
82
|
+
i = i + 1
|
83
|
+
end
|
84
|
+
return productions
|
85
|
+
end
|
86
|
+
|
87
|
+
def chompLambda(string)
|
88
|
+
if !@valid
|
89
|
+
@valid = (string.length==0)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def chompChar(string, char)
|
94
|
+
if !@valid
|
95
|
+
@valid = (string.length == 1 && string[0] == char)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def analyzeInput(productions, line, state)
|
100
|
+
# Right Grammar S -> aS | a
|
101
|
+
prods = productions[state].getRight()
|
102
|
+
prods = prods.sort_by(&:length)
|
103
|
+
prods.reverse!
|
104
|
+
prods.each do |p|
|
105
|
+
#Check for lambda
|
106
|
+
if p.length == 0
|
107
|
+
if line.length == 0
|
108
|
+
return true
|
109
|
+
else
|
110
|
+
return false
|
111
|
+
end
|
112
|
+
elsif p.length == 1
|
113
|
+
# Check for ending
|
114
|
+
# For a terminal only production
|
115
|
+
if p[0].downcase == p[0]
|
116
|
+
# Terminal
|
117
|
+
ret = p[0] == line[0] && line.length == 1
|
118
|
+
return ret
|
119
|
+
else
|
120
|
+
# Non-terminal
|
121
|
+
ret = analyzeInput(productions, line, p[0])
|
122
|
+
return ret
|
123
|
+
end
|
124
|
+
elsif p.length > 1
|
125
|
+
if line.length > 1
|
126
|
+
# For a non-terminal and terminal production
|
127
|
+
if p[0].downcase != p[0]
|
128
|
+
# S -> Sa
|
129
|
+
puts "Example S -> aS"
|
130
|
+
return false if p[1] != line[0]
|
131
|
+
newLine = line
|
132
|
+
newLine.slice! p[1]
|
133
|
+
ret = analyzeInput(productions, newLine, p[0])
|
134
|
+
return ret
|
135
|
+
else
|
136
|
+
# S -> aS
|
137
|
+
return false if p[0] != line[0]
|
138
|
+
newLine = line
|
139
|
+
newLine.reverse!
|
140
|
+
newLine.slice! p[0]
|
141
|
+
newLine.reverse!
|
142
|
+
ret = analyzeInput(productions, newLine, p[1])
|
143
|
+
return ret
|
144
|
+
end
|
145
|
+
elsif line.length == 1
|
146
|
+
# For a non-terminal and terminal production
|
147
|
+
if p[0].downcase != p[0]
|
148
|
+
# S -> Sa
|
149
|
+
return true if productions[p[0]].getRight.include? ""
|
150
|
+
return false if p[1] != line[0]
|
151
|
+
return true if productions[state].getRight.include?(p[1]) && p[1] == line[0]
|
152
|
+
newLine = line
|
153
|
+
newLine.slice! p[1]
|
154
|
+
puts p[0]
|
155
|
+
ret = analyzeInput(productions, newLine, p[0])
|
156
|
+
return ret
|
157
|
+
else
|
158
|
+
# S -> aS
|
159
|
+
return true if productions[p[1]].getRight.include?("")
|
160
|
+
return false if p[0] != line[0]
|
161
|
+
return true if (productions[state].getRight.include?(p[0]) && p[0] == line[0])
|
162
|
+
newLine = line
|
163
|
+
newLine.reverse!
|
164
|
+
newLine.slice! p[0]
|
165
|
+
newLine.reverse!
|
166
|
+
ret = analyzeInput(productions, newLine, p[1])
|
167
|
+
return ret
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def analyze(file, line)
|
175
|
+
productions = createProductions(readFile(file))
|
176
|
+
@valid = analyzeInput(productions, line, "S")
|
177
|
+
puts @valid
|
178
|
+
return @valid
|
179
|
+
end
|
180
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!--Created with JFLAP 6.4.--><structure>
|
2
|
+
<type>grammar</type>
|
3
|
+
<!--The list of productions.-->
|
4
|
+
<production>
|
5
|
+
<left>S</left>
|
6
|
+
<right>aA</right>
|
7
|
+
</production>
|
8
|
+
<production>
|
9
|
+
<left>A</left>
|
10
|
+
<right>aS</right>
|
11
|
+
</production>
|
12
|
+
<production>
|
13
|
+
<left>A</left>
|
14
|
+
<right>a</right>
|
15
|
+
</production>
|
16
|
+
</structure>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: SEATC
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Salvador Guerra Delgado
|
@@ -20,7 +20,11 @@ files:
|
|
20
20
|
- Rakefile
|
21
21
|
- bin/Finite Automaton
|
22
22
|
- lib/Finite Automaton Analyzer.rb
|
23
|
+
- lib/Regular Expression.rb
|
24
|
+
- lib/Regular Grammar Analyzer.rb
|
23
25
|
- samples/Finite Automaton.jff
|
26
|
+
- samples/Regular Expression.jff
|
27
|
+
- samples/Regular Grammar.jff
|
24
28
|
homepage: http://rubygems.org/gems/SEATC
|
25
29
|
licenses: []
|
26
30
|
metadata: {}
|
@@ -40,7 +44,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
40
44
|
version: '0'
|
41
45
|
requirements: []
|
42
46
|
rubyforge_project:
|
43
|
-
rubygems_version: 2.
|
47
|
+
rubygems_version: 2.5.2.1
|
44
48
|
signing_key:
|
45
49
|
specification_version: 3
|
46
50
|
summary: SEATC
|