rley 0.0.11 → 0.0.12
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 +8 -8
- data/CHANGELOG.md +4 -0
- data/lib/rley/constants.rb +1 -1
- data/lib/rley/syntax/grammar.rb +27 -1
- data/lib/rley/syntax/grm_symbol.rb +4 -1
- data/lib/rley/syntax/non_terminal.rb +22 -0
- data/lib/rley/syntax/terminal.rb +7 -0
- data/spec/rley/parser/earley_parser_spec.rb +31 -0
- data/spec/rley/syntax/grammar_spec.rb +4 -0
- data/spec/rley/syntax/non_terminal_spec.rb +11 -0
- data/spec/rley/syntax/terminal_spec.rb +4 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YWJmOTI2YmJiNWQwNDY5YjM3ZTdmMzdlZmEyMDE0ODRiM2Q1N2Y4YQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZjNmODNiOWZlYTc3MzcyNGUzZDhiNWVhMTBjNDRjZmU2OTg3NTM4Yg==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
OWRiMmM1NzQ3ZjdjZjAwYTZlNWFlYzgxMjliY2M2YzQ2MzZjMTNlMmE2NjI5
|
10
|
+
YTAxNWNhMGMxMjY1ODU3NzI4YTFhNmNmNzkxMzAzNjUyMjZjZjBlM2U5ZDhi
|
11
|
+
ZmY0MmU3ZTgxNmJjYTk3ZTc3MTg1MmFlYWNhYjhiMjJjOTljOTU=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NzQyYmYyNzc5ZmIyNTVjMWJkOTVjNzI5NzM2N2Y5N2ZkN2Y1NmRlODcwNjAz
|
14
|
+
MzRiNGIyNGIxNGExMGJlNjY4ZjYxYTc5YTc4Mjg1ODEyZGEyNGExOTM3N2Iw
|
15
|
+
ODFkMGU4MjIxNTZmZjczNWNiYjUzMjYwYTZhZjkxNTRmZjg2MmU=
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
### 0.0.12 / 2014-11-17
|
2
|
+
* [CHANGE] Classes `Terminal` and `NonTerminal` added new method nullable?
|
3
|
+
|
4
|
+
|
1
5
|
### 0.0.11 / 2014-11-16
|
2
6
|
* [CHANGE] Usage of `GrammarBuilder`simplified: the call to method `GrammarBuilder#add_non_terminal` isn't necessary. Method is removed
|
3
7
|
* [CHANGE] Updated the `examples` folder accordingly.
|
data/lib/rley/constants.rb
CHANGED
data/lib/rley/syntax/grammar.rb
CHANGED
@@ -19,7 +19,8 @@ module Rley # This module is used as a namespace
|
|
19
19
|
# The list of grammar symbols in the language.
|
20
20
|
attr_reader(:symbols)
|
21
21
|
|
22
|
-
# @param theProduction [Array of Production]
|
22
|
+
# @param theProduction [Array of Production] the list of productions
|
23
|
+
# of the grammar.
|
23
24
|
def initialize(theProductions)
|
24
25
|
@rules = []
|
25
26
|
@symbols = []
|
@@ -27,6 +28,12 @@ module Rley # This module is used as a namespace
|
|
27
28
|
# TODO: use topological sorting
|
28
29
|
@start_symbol = valid_productions[0].lhs
|
29
30
|
valid_productions.each { |prod| add_production(prod) }
|
31
|
+
compute_nullable
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [Array] The list of non-terminals in the grammar.
|
35
|
+
def non_terminals()
|
36
|
+
return symbols.select { |s| s.kind_of?(NonTerminal) }
|
30
37
|
end
|
31
38
|
|
32
39
|
private
|
@@ -49,6 +56,25 @@ module Rley # This module is used as a namespace
|
|
49
56
|
@symbols << symb
|
50
57
|
end
|
51
58
|
end
|
59
|
+
|
60
|
+
# For each non-terminal determine whether it is nullable or not.
|
61
|
+
def compute_nullable()
|
62
|
+
# Do the obvious cases
|
63
|
+
rules.each do |prod|
|
64
|
+
next unless prod.rhs.empty?
|
65
|
+
prod.lhs.nullable = true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
=begin
|
69
|
+
prods4nonterm = productions.group_by { |prod| prod.lhs }
|
70
|
+
prods4nonterm.each_pair do |(lhs, prods)|
|
71
|
+
|
72
|
+
|
73
|
+
to_process = non_terminals.select { |nt| nt.nullable?.nil? }
|
74
|
+
|
75
|
+
until to_process.empty? do
|
76
|
+
|
77
|
+
=end
|
52
78
|
end # class
|
53
79
|
end # module
|
54
80
|
end # module
|
@@ -2,13 +2,16 @@ module Rley # This module is used as a namespace
|
|
2
2
|
module Syntax # This module is used as a namespace
|
3
3
|
# Abstract class for grammar symbols.
|
4
4
|
# A grammar symbol is an element that appears in grammar rules.
|
5
|
-
class GrmSymbol
|
5
|
+
class GrmSymbol
|
6
6
|
# The name of the grammar symbol
|
7
7
|
attr_reader(:name)
|
8
8
|
|
9
|
+
# Constructor.
|
10
|
+
# aName [String] The name of the grammar symbol.
|
9
11
|
def initialize(aName)
|
10
12
|
@name = aName.dup
|
11
13
|
end
|
14
|
+
|
12
15
|
end # class
|
13
16
|
end # module
|
14
17
|
end # module
|
@@ -5,9 +5,31 @@ module Rley # This module is used as a namespace
|
|
5
5
|
# A non-terminal symbol (sometimes called a syntactic variable) represents
|
6
6
|
# a composition of terminal or non-terminal symbols
|
7
7
|
class NonTerminal < GrmSymbol
|
8
|
+
|
9
|
+
# Constructor.
|
10
|
+
# @param aName [String] The name of the grammar symbol.
|
8
11
|
def initialize(aName)
|
9
12
|
super(aName)
|
10
13
|
end
|
14
|
+
|
15
|
+
public
|
16
|
+
|
17
|
+
# @return [false/true] Return true if the symbol derives
|
18
|
+
# the empty string. As non-terminal symbol is nullable when it can
|
19
|
+
# can match to zero input token.
|
20
|
+
# The "nullability" of a non-terminal can practically be determined once
|
21
|
+
# all the production rules of the grammar are specified.
|
22
|
+
def nullable?()
|
23
|
+
return @nullable
|
24
|
+
end
|
25
|
+
|
26
|
+
# Set the nullable flag.
|
27
|
+
# @param aBoolean [true/false]
|
28
|
+
def nullable=(aBoolean)
|
29
|
+
@nullable = aBoolean
|
30
|
+
end
|
31
|
+
|
32
|
+
|
11
33
|
end # class
|
12
34
|
end # module
|
13
35
|
end # module
|
data/lib/rley/syntax/terminal.rb
CHANGED
@@ -7,9 +7,16 @@ module Rley # This module is used as a namespace
|
|
7
7
|
# defined the grammar.
|
8
8
|
class Terminal < GrmSymbol
|
9
9
|
|
10
|
+
# Constructor.
|
11
|
+
# aName [String] The name of the grammar symbol.
|
10
12
|
def initialize(aName)
|
11
13
|
super(aName)
|
12
14
|
end
|
15
|
+
|
16
|
+
# @return [false] Return true if the symbol derives
|
17
|
+
# the empty string. As terminal symbol corresponds to a input token
|
18
|
+
# it is by definition non-nullable.
|
19
|
+
def nullable?() false; end
|
13
20
|
end # class
|
14
21
|
|
15
22
|
end # module
|
@@ -3,6 +3,7 @@ require_relative '../../spec_helper'
|
|
3
3
|
require_relative '../../../lib/rley/syntax/verbatim_symbol'
|
4
4
|
require_relative '../../../lib/rley/syntax/non_terminal'
|
5
5
|
require_relative '../../../lib/rley/syntax/production'
|
6
|
+
require_relative '../../../lib/rley/syntax/grammar_builder'
|
6
7
|
require_relative '../../../lib/rley/parser/token'
|
7
8
|
# Load the class under test
|
8
9
|
require_relative '../../../lib/rley/parser/earley_parser'
|
@@ -344,6 +345,36 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
344
345
|
]
|
345
346
|
compare_state_set(parse_result.chart[5], expectations)
|
346
347
|
end
|
348
|
+
|
349
|
+
|
350
|
+
it 'should parse an ambiguous grammar' do
|
351
|
+
# Grammar 3: A ambiguous arithmetic expression language
|
352
|
+
# (based on example in article on Earley's algorithm in Wikipedia)
|
353
|
+
# P ::= S.
|
354
|
+
# S ::= S "+" S.
|
355
|
+
# S ::= S "*" S.
|
356
|
+
# S ::= T.
|
357
|
+
# T ::= an integer number token.
|
358
|
+
t_int = Syntax::Literal.new('integer', /[-+]?\d+/)
|
359
|
+
t_plus = Syntax::VerbatimSymbol.new('+')
|
360
|
+
t_star = Syntax::VerbatimSymbol.new('*')
|
361
|
+
|
362
|
+
builder = Syntax::GrammarBuilder.new
|
363
|
+
builder.add_terminals(t_int, t_plus, t_star)
|
364
|
+
builder.add_production('P' => 'S')
|
365
|
+
builder.add_production('S' => %w(S + S))
|
366
|
+
builder.add_production('S' => %w(S * S))
|
367
|
+
builder.add_production('S' => 'L')
|
368
|
+
builder.add_production('L' => 'integer')
|
369
|
+
tokens = [
|
370
|
+
Token.new('2', t_int),
|
371
|
+
Token.new('+', t_plus),
|
372
|
+
Token.new('3', t_int),
|
373
|
+
Token.new('*', t_star),
|
374
|
+
Token.new('4', t_int)
|
375
|
+
]
|
376
|
+
parse_result = subject.parse(tokens)
|
377
|
+
end
|
347
378
|
|
348
379
|
|
349
380
|
it 'should parse an invalid simple input' do
|
@@ -138,6 +138,10 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
138
138
|
it 'should know all its symbols' do
|
139
139
|
expect(subject.symbols).to eq([nt_S, nt_A, a_, c_, b_])
|
140
140
|
end
|
141
|
+
|
142
|
+
it 'should know all its non-terminal symbols' do
|
143
|
+
expect(subject.non_terminals).to eq([nt_S, nt_A])
|
144
|
+
end
|
141
145
|
end # context
|
142
146
|
|
143
147
|
end # describe
|
@@ -19,6 +19,17 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
19
19
|
end
|
20
20
|
end # context
|
21
21
|
|
22
|
+
|
23
|
+
context 'Provided services:' do
|
24
|
+
it 'should know whether it is nullable' do
|
25
|
+
expect(subject.nullable?).to be_nil
|
26
|
+
subject.nullable = true
|
27
|
+
expect(subject).to be_nullable
|
28
|
+
subject.nullable = false
|
29
|
+
expect(subject).not_to be_nullable
|
30
|
+
end
|
31
|
+
end # context
|
32
|
+
|
22
33
|
end # describe
|
23
34
|
end # module
|
24
35
|
end # module
|
@@ -17,6 +17,10 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
17
17
|
it 'should know its name' do
|
18
18
|
expect(subject.name).to eq(sample_name)
|
19
19
|
end
|
20
|
+
|
21
|
+
it "should know that isn't nullable" do
|
22
|
+
expect(subject).not_to be_nullable
|
23
|
+
end
|
20
24
|
end # context
|
21
25
|
|
22
26
|
end # describe
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rley
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dimitri Geshef
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|