SEATC 0.0.4 → 0.0.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 66f327a45f65437e97b2156761a3b883888a6b94
4
- data.tar.gz: 6f0cf8d8a198887c54fb4f91517ab0978875db27
3
+ metadata.gz: 6b1ed631327b6eefa9d013e3a8b0e2cd423558de
4
+ data.tar.gz: 4f248e1b1f23f7bf1aacfc2be63f4e51ddc49bf2
5
5
  SHA512:
6
- metadata.gz: f9a3893997079096c785eae03bb4d9603a85213127829083fac635a7425fab0e1c4a05dba6b52ee5fa2c95f42967914a583a8dbe980721b751328d835ca53dea
7
- data.tar.gz: 772c965d67357ed2259d15bf0c1c6ac61ca9e2a1c7f3b6ec8d501aed254576e3cad9ff9eb5f03bce83206d31b8dcda6ce9248ad2bb098bb64cd1cfb6bacce91c
6
+ metadata.gz: 451e0ef6aa23b421096333ed51b408efb1df8b755e4dcc821f4f163797802c438e300b3c959b95cace611682ab4b14dc144e5992462e1069b57163fdbd0a7a67
7
+ data.tar.gz: 115f64c041986817124d9eaba62b7fef72ac0ac9d2fe64bf1f2ff8602252294322e2cb271a8316562609631e2270673ae8aa040ac5aef6dcbb30d693474257ff
@@ -0,0 +1,80 @@
1
+ require 'thread'
2
+ load 'Grammar Reader.rb'
3
+
4
+ class GrammarAnalyzer
5
+ attr_accessor :mutex, :valid
6
+
7
+ def initialize
8
+ @mutex = Mutex.new
9
+ @valid = false
10
+ end
11
+
12
+ def println(s)
13
+ @mutex.synchronize {
14
+ puts s
15
+ }
16
+ end
17
+
18
+ def isNT(char)
19
+ return "A" <= char && char <= "Z"
20
+ end
21
+
22
+ def removeFirst(line)
23
+ line.reverse!
24
+ line.chop!
25
+ line.reverse!
26
+ end
27
+
28
+ def canContinue(prod, line)
29
+ p = String.new prod
30
+ s = 0
31
+ for i in 0...p.length
32
+ s = s + 1 if !isNT(p[i])
33
+ end
34
+ # puts s <= line.length
35
+ return s <= line.length
36
+ end
37
+
38
+ def analyzer(prod, line, prods)
39
+ #puts "Analyzing " + prod
40
+ while canContinue(prod, line)
41
+ if prod.length == 0
42
+ if line.length == 0
43
+ @valid = true
44
+ #println "Exito"
45
+ else
46
+ #println "Error"
47
+ end
48
+ return
49
+ end
50
+ if isNT(prod[0])
51
+ prods[prod[0]].each do |p|
52
+ t = Thread.new { analyzer(String.new(p + prod.slice(1, prod.length - 1)), String.new(line), prods)}
53
+ t.join
54
+ end
55
+ return
56
+ end
57
+ if prod[0] == line[0]
58
+ removeFirst line
59
+ removeFirst prod
60
+ else
61
+ # println "Error en el analisis"
62
+ return
63
+ end
64
+ end
65
+ end
66
+
67
+ def analyze(file, line)
68
+ reader = GrammarReader.new
69
+ prods = reader.createProductions(reader.readFile(file))
70
+ prods['S'].each do |p|
71
+ t = Thread.new { analyzer(String.new(p), String.new(line), prods)}
72
+ t.join
73
+ end
74
+ ret = @valid
75
+ end
76
+
77
+ end
78
+
79
+ ga = GrammarAnalyzer.new
80
+ puts ga.analyze("../samples/Regular Grammar.jff", "aaaa")
@@ -0,0 +1,69 @@
1
+ SYNTAX_ERROR = 1
2
+ PRODUCTION_ERROR = 2
3
+
4
+ class GrammarReader
5
+ attr_accessor :error
6
+
7
+ def initialize()
8
+ @error = 0
9
+ end
10
+ def getLeft(modified)
11
+ modified.slice! "\t\t<left>"
12
+ ret = modified[0]
13
+ end
14
+
15
+ def getRight(modified)
16
+ modified.slice! "\t\t<right>"
17
+ ret = ""
18
+ while(modified[0] != "<")
19
+ sliced = modified[0]
20
+ modified.slice! sliced
21
+ ret = ret + sliced
22
+ end
23
+ return ret
24
+ end
25
+
26
+ #returns an Array containing the lines from the file
27
+ def readFile(file)
28
+ file = File.new(file, "r")
29
+ line = file.read
30
+ file.close
31
+ lines = line.split("\n")
32
+ end
33
+
34
+ #returns the Hash containing the productions
35
+ def createProductions(lines)
36
+ productions = Hash.new
37
+ if !lines[0].include? "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><!--Created with JFLAP 6.4.--><structure>&#13;"
38
+ @error = SYNTAX_ERROR
39
+ return productions
40
+ end
41
+ if !lines[1].include? "\t<type>grammar</type>&#13;"
42
+ @error = SYNTAX_ERROR
43
+ return productions
44
+ end
45
+ counter = 3
46
+ i = 0
47
+ modified = lines[counter]
48
+ while(modified.include? "production")
49
+ modified = lines[counter + 1]
50
+ left = getLeft(modified)
51
+ modified = lines[counter + 2]
52
+ right = getRight(modified)
53
+ while right[0] == "\t"
54
+ right.slice! "\t"
55
+ end
56
+ if right.length > 2
57
+ @error = PRODUCTION_ERROR
58
+ end
59
+ counter = counter + 4
60
+ modified = lines[counter]
61
+ if productions[left] == nil
62
+ productions[left] = Array.new
63
+ end
64
+ productions[left].push(right)
65
+ i = i + 1
66
+ end
67
+ return productions
68
+ end
69
+ end
@@ -0,0 +1,227 @@
1
+ class PDATransition
2
+ attr_accessor :destination, :push, :pop
3
+ def initialize(destination, push, pop)
4
+ @destination = destination
5
+ @push = push
6
+ @pop = pop
7
+ end
8
+ def getDestination()
9
+ return @destination
10
+ end
11
+ end
12
+
13
+ class PDAState
14
+ @id
15
+ @nombre
16
+ @transitions
17
+ @final
18
+ def initialize(id, nombre, final)
19
+ @id = id
20
+ @nombre = nombre
21
+ @transitions = Hash.new
22
+ @final = final
23
+ end
24
+ def addTrans(char, to, pop, push)
25
+ if @transitions[char] == nil
26
+ @transitions[char] = Hash.new
27
+ end
28
+ @transitions[char][to] = PDATransition.new to, push, pop
29
+ end
30
+ def transAt(char)
31
+ ret = @transitions[char]
32
+ end
33
+ def final()
34
+ ret = @final
35
+ end
36
+ end
37
+
38
+ class PDAAnalyzer
39
+ @valid = false
40
+ def getStateID(modified)
41
+ modified.slice! "\t\t<state id=\""
42
+ lastQuota = true
43
+ id = 0
44
+ while(lastQuota)
45
+ id = id * 10
46
+ char = modified[0]
47
+ modified.slice! modified[0]
48
+ lastQuota = (modified[0] != "\"")
49
+ id = id + char.to_i
50
+ end
51
+ id = id
52
+ end
53
+
54
+ def getStateName(modified)
55
+ modified.slice! "\" name=\""
56
+ lastQuota = true
57
+ id = ""
58
+ while(lastQuota)
59
+ id = id + modified[0]
60
+ modified.slice! modified[0]
61
+ lastQuota = (modified[0] != "\"")
62
+ end
63
+ id = id
64
+ end
65
+
66
+ def readPush(modified)
67
+ lastQuota = true
68
+ id = ""
69
+ while(lastQuota)
70
+ id = id + modified[0]
71
+ modified.slice! modified[0]
72
+ lastQuota = (modified[0] != "<")
73
+ end
74
+ id = id
75
+ end
76
+
77
+ def readPop(modified)
78
+ lastQuota = true
79
+ id = ""
80
+ while(lastQuota)
81
+ id = id + modified[0]
82
+ modified.slice! modified[0]
83
+ lastQuota = (modified[0] != "<")
84
+ end
85
+ id = id
86
+ end
87
+
88
+ def readTransInt(modified)
89
+ lastQuota = true
90
+ id = 0
91
+ while(lastQuota)
92
+ id = id * 10
93
+ char = modified[0]
94
+ modified.slice! modified[0]
95
+ lastQuota = (modified[0] != "<")
96
+ id = id + char.to_i
97
+ end
98
+ id = id
99
+
100
+ end
101
+
102
+ def validateString(initial, states, line, stack)
103
+ st = initial
104
+ usedLine = String.new line
105
+ if(usedLine != "")
106
+ char = usedLine[0]
107
+ usedLine.slice! char
108
+ sts = states[st].transAt(char)
109
+ if sts != nil
110
+ sts.each do |transition|
111
+ pushable = String.new transition[1].push
112
+ if(stack.length == 0 && transition[1].pop != "")
113
+ return false
114
+ end
115
+ if(transition[1].pop != "")
116
+ pop = stack.pop
117
+ if(pop != transition[1].pop)
118
+ return false
119
+ end
120
+ end
121
+ pushable.reverse!
122
+ while(pushable!="")
123
+ stack.push pushable[0]
124
+ pushable.slice! pushable[0]
125
+ end
126
+ v = validateString(transition[0], states, usedLine, stack)
127
+ end
128
+ end
129
+ else
130
+ if(states[st].final == 1 || stack.length == 0)
131
+ @valid = true
132
+ end
133
+ end
134
+ end
135
+
136
+ #Returns true if the automaton ends in final state, returns false otherwise
137
+ def analyze(sourceFile, testString)
138
+ file = File.new(sourceFile, "r")
139
+ line = file.read
140
+ file.close
141
+ counter = 1
142
+ lines = line.split("\n")
143
+ for lin in lines
144
+ counter = counter + 1
145
+ end
146
+ if !lines[0].include? "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><!--Created with JFLAP 6.4.--><structure>"
147
+ return false
148
+ end
149
+ # Check if pushdown automaton
150
+ if !lines[1].match "<type>pda</type>"
151
+ return false
152
+ end
153
+ states = []
154
+ counter = 4
155
+ i = 0
156
+ initialState = nil
157
+ modified = lines[counter]
158
+ while(modified.include? "state")
159
+ final = 0
160
+ aux = counter
161
+ id = getStateID(modified)
162
+ nombre = getStateName(modified)
163
+ if(lines[counter + 3 ].include? "initial")
164
+ aux = aux + 1
165
+ initialState = id
166
+ end
167
+ if(lines[aux + 3].include? "final")
168
+ final = 1
169
+ aux = aux + 1
170
+ end
171
+ counter = aux + 4
172
+ modified = lines[counter]
173
+ states[id] = PDAState.new(id, nombre, final)
174
+ i = i + 1
175
+ end
176
+ counter = counter + 1
177
+ modified = lines[counter]
178
+ while(modified.include? "transition")
179
+ counter = counter + 1
180
+ modified = lines[counter]
181
+ modified.slice! "\t\t\t<from>"
182
+ from = readTransInt(modified)
183
+ counter = counter + 1
184
+ modified = lines[counter]
185
+ modified.slice! "\t\t\t<to>"
186
+ to = readTransInt(modified)
187
+ counter = counter + 1
188
+ modified = lines[counter]
189
+ modified.slice! "\t\t\t<read>"
190
+ read = modified[0]
191
+ counter = counter + 1
192
+ modified = lines[counter]
193
+ if(modified.include? "<pop>")
194
+ modified.slice! "\t\t\t<pop>"
195
+ pop = readPop(modified)
196
+ else
197
+ pop=""
198
+ end
199
+ counter = counter + 1
200
+ modified = lines[counter]
201
+ if(modified.include? "<push>")
202
+ modified.slice! "\t\t\t<push>"
203
+ push = readPush(modified)
204
+ else
205
+ push=""
206
+ end
207
+ states[from].addTrans(read, to, pop, push)
208
+ counter = counter + 2
209
+ modified = lines[counter]
210
+ end
211
+ #Validate
212
+ lin = testString
213
+ stack = Array.new
214
+ valid = validateString(initialState, states, lin, stack)
215
+ if @valid
216
+ ret = true
217
+ else
218
+ ret = false
219
+ end
220
+ end
221
+ end
222
+
223
+ ndfa= PDAAnalyzer.new
224
+ puts ndfa.analyze("../samples/Pushdown.jff", "aabb")
225
+
226
+ <% ndfa= PDAAnalyzer.new %>
227
+ <% res = ndfa.analyze("../samples/Pushdown.jff", "aabb") %>
@@ -30,3 +30,5 @@ class RegularExpression
30
30
  end
31
31
  end
32
32
  end
33
+ regex = RegularExpression.new
34
+ puts regex.analyze("../samples/Regular Expression.jff", "ab")
@@ -178,3 +178,6 @@ class RegularGrammar
178
178
  return @valid
179
179
  end
180
180
  end
181
+
182
+ rg = RegularGrammar.new
183
+ rg.analyze("../samples/Regular Grammar.jff", "aaaaaaa")
@@ -0,0 +1,27 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?><!--Created with JFLAP 6.4.--><structure>
2
+ <type>pda</type>
3
+ <automaton>
4
+ <!--The list of states.-->
5
+ <state id="0" name="q0">
6
+ <x>79.0</x>
7
+ <y>137.0</y>
8
+ <initial/>
9
+ <final/>
10
+ </state>
11
+ <!--The list of transitions.-->
12
+ <transition>
13
+ <from>0</from>
14
+ <to>0</to>
15
+ <read>a</read>
16
+ <pop/>
17
+ <push>A</push>
18
+ </transition>
19
+ <transition>
20
+ <from>0</from>
21
+ <to>0</to>
22
+ <read>b</read>
23
+ <pop>A</pop>
24
+ <push/>
25
+ </transition>
26
+ </automaton>
27
+ </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
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Salvador Guerra Delgado
@@ -11,7 +11,7 @@ cert_chain: []
11
11
  date: 2018-01-23 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A gem for development on SEATC, can be used for other system that requires
14
- automaton analysis
14
+ automaton and grammars analysis
15
15
  email: salvador.guerra.delgado2@gmail.com
16
16
  executables: []
17
17
  extensions: []
@@ -20,9 +20,13 @@ files:
20
20
  - Rakefile
21
21
  - bin/Finite Automaton
22
22
  - lib/Finite Automaton Analyzer.rb
23
+ - lib/Grammar Analyzer.rb
24
+ - lib/Grammar Reader.rb
25
+ - lib/PDA.rb
23
26
  - lib/Regular Expression.rb
24
27
  - lib/Regular Grammar Analyzer.rb
25
28
  - samples/Finite Automaton.jff
29
+ - samples/Pushdown.jff
26
30
  - samples/Regular Expression.jff
27
31
  - samples/Regular Grammar.jff
28
32
  homepage: http://rubygems.org/gems/SEATC
@@ -44,7 +48,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
44
48
  version: '0'
45
49
  requirements: []
46
50
  rubyforge_project:
47
- rubygems_version: 2.5.2.1
51
+ rubygems_version: 2.6.14
48
52
  signing_key:
49
53
  specification_version: 3
50
54
  summary: SEATC