rley 0.0.10 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/CHANGELOG.md +4 -0
- data/examples/grammars/grammar_L0.rb +1 -4
- data/examples/grammars/grammar_abc.rb +0 -1
- data/lib/rley/constants.rb +1 -1
- data/lib/rley/parser/earley_parser.rb +2 -1
- data/lib/rley/syntax/grammar_builder.rb +23 -12
- data/spec/rley/syntax/grammar_builder_spec.rb +9 -14
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MTE3MWVhNjUzOTkzNjM3N2E3MjdjYzE5MWE1MDEyMmNkZGM3NGJiYw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NGM4ZGI2NTY2ZDU1NDU5YzQxMjFiNWVlZmU0YWU3MDhjMGMxYTQ5OA==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NDA1NzYzZTU2NjY5MDdlMGJkYjZiZGEzZGY5YTkxMzYxZTk3NTNmNDlhZGRl
|
10
|
+
NTUwZjRkYTZlZGIyYTAxYWI2NGE2MWVmMWNiN2JjYTY4MDU2ZDgwYjIyNDY1
|
11
|
+
Y2E3ZjViZTkyM2Q5ZTY1ZjJiMmViNmNlZGFlODE3MzE5YjhiM2Y=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NzUxNmMzMjZkMWM2Y2NmMzJmY2U3ZTA3ZDYyYmVkZDI2MjAxYTc2MWIxYmRj
|
14
|
+
NzYyMzRjOGQxZWIxOTFlN2U4OGUzMTMzMzU5ZjNhMTU0OTkwMDk2MmMzMmU5
|
15
|
+
NTZiNTMwZjc4MjBlZWJjOWJmOWE4MWFmZDcyYWQyZWZlZTdmN2U=
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
### 0.0.11 / 2014-11-16
|
2
|
+
* [CHANGE] Usage of `GrammarBuilder`simplified: the call to method `GrammarBuilder#add_non_terminal` isn't necessary. Method is removed
|
3
|
+
* [CHANGE] Updated the `examples` folder accordingly.
|
4
|
+
|
1
5
|
### 0.0.10 / 2014-11-15
|
2
6
|
* [NEW] New folder `examples` added with two examples of grammar creation
|
3
7
|
|
@@ -12,14 +12,11 @@ builder.add_terminals('Noun', 'Verb', 'Adjective')
|
|
12
12
|
builder.add_terminals('Pronoun', 'Proper-Noun', 'Determiner')
|
13
13
|
builder.add_terminals('Preposition', 'Conjunction')
|
14
14
|
|
15
|
-
# Enumerate the non-terminal symbols...
|
16
|
-
builder.add_non_terminals('S', 'NP', 'Nominal', 'VP', 'PP')
|
17
|
-
|
18
15
|
# Now the production rules...
|
19
16
|
builder.add_production('S'=> ['NP', 'VP']) # e.g. I + want a morning flight
|
20
17
|
builder.add_production('NP' => 'Pronoun') # e.g. I
|
21
18
|
builder.add_production('NP' => 'Proper-Noun') # e.g. Los Angeles
|
22
|
-
builder.add_production('NP' => ['
|
19
|
+
builder.add_production('NP' => ['Determiner', 'Nominal']) # e.g. a + flight
|
23
20
|
builder.add_production('Nominal' => %w(Nominal Noun)) # morning + flight
|
24
21
|
builder.add_production('Nominal' => 'Noun') # e.g. flights
|
25
22
|
builder.add_production('VP' => 'Verb') # e.g. do
|
@@ -12,7 +12,6 @@ require 'rley' # Load the gem
|
|
12
12
|
# Let's create the grammar step-by-step with the grammar builder:
|
13
13
|
builder = Rley::Syntax::GrammarBuilder.new
|
14
14
|
builder.add_terminals('a', 'b', 'c')
|
15
|
-
builder.add_non_terminals('S', 'A')
|
16
15
|
builder.add_production('S' => 'A')
|
17
16
|
builder.add_production('A' => %w(a A c))
|
18
17
|
builder.add_production('A' => 'b')
|
data/lib/rley/constants.rb
CHANGED
@@ -4,7 +4,7 @@ require_relative 'parsing'
|
|
4
4
|
|
5
5
|
module Rley # This module is used as a namespace
|
6
6
|
module Parser # This module is used as a namespace
|
7
|
-
# Implementation of a parser that uses the Earley parsing algorithm.
|
7
|
+
# Implementation of a parser that uses the Earley parsing algorithm.
|
8
8
|
class EarleyParser
|
9
9
|
# The grammar of the language.
|
10
10
|
attr_reader(:grammar)
|
@@ -29,6 +29,7 @@ module Rley # This module is used as a namespace
|
|
29
29
|
@next_mapping = build_next_mapping(dotted_items)
|
30
30
|
end
|
31
31
|
|
32
|
+
# Parse a sequence of input tokens.
|
32
33
|
# @param aTokenSequence [Array] Array of Tokens objects returned by a
|
33
34
|
# tokenizer/scanner/lexer.
|
34
35
|
# @return a Parsing object that embeds the parse result.
|
@@ -22,7 +22,7 @@ module Rley # This module is used as a namespace
|
|
22
22
|
@symbols = {}
|
23
23
|
@productions = []
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
# Retrieve a grammar symbol from its name.
|
27
27
|
# Raise an exception if not found.
|
28
28
|
# @param [aSymbolName] the name of a symbol grammar.
|
@@ -39,23 +39,15 @@ module Rley # This module is used as a namespace
|
|
39
39
|
symbols.merge!(new_symbs)
|
40
40
|
end
|
41
41
|
|
42
|
-
# Add the non-terminal symbols of the language
|
43
|
-
# nonTerminalSymbols [String or NonTerminal] one or more non-terminal
|
44
|
-
# symbols to add to the grammar.
|
45
|
-
def add_non_terminals(*nonTerminalSymbols)
|
46
|
-
new_symbs = build_symbols(NonTerminal, nonTerminalSymbols)
|
47
|
-
symbols.merge!(new_symbs)
|
48
|
-
end
|
49
|
-
|
50
42
|
# builder.add_production('A' => ['a', 'A', 'c'])
|
51
43
|
def add_production(aProductionRepr)
|
52
44
|
aProductionRepr.each_pair do |(lhs_name, rhs_repr)|
|
53
|
-
lhs =
|
45
|
+
lhs = get_nonterminal(lhs_name)
|
54
46
|
case rhs_repr
|
55
47
|
when Array
|
56
|
-
rhs_constituents = rhs_repr.map { |name|
|
48
|
+
rhs_constituents = rhs_repr.map { |name| get_nonterminal(name) }
|
57
49
|
when String
|
58
|
-
rhs_constituents = [
|
50
|
+
rhs_constituents = [ get_nonterminal(rhs_repr) ]
|
59
51
|
end
|
60
52
|
new_prod = Production.new(lhs, rhs_constituents)
|
61
53
|
productions << new_prod
|
@@ -69,6 +61,13 @@ module Rley # This module is used as a namespace
|
|
69
61
|
if productions.empty?
|
70
62
|
fail StandardError, 'No production found for grammar'
|
71
63
|
end
|
64
|
+
|
65
|
+
# Check that each non-terminal appears at least once in lhs.
|
66
|
+
all_non_terminals = symbols.values.select { |s| s.is_a?(NonTerminal) }
|
67
|
+
all_non_terminals.each do |n_term|
|
68
|
+
next if productions.any? { |prod| n_term == prod.lhs }
|
69
|
+
fail StandardError, "Nonterminal #{n_term.name} not rewritten"
|
70
|
+
end
|
72
71
|
|
73
72
|
return Grammar.new(productions.dup)
|
74
73
|
end
|
@@ -107,6 +106,18 @@ module Rley # This module is used as a namespace
|
|
107
106
|
|
108
107
|
return a_symbol
|
109
108
|
end
|
109
|
+
|
110
|
+
# Retrieve the non-terminal symbol with given name.
|
111
|
+
# If it doesn't exist yet, then it is created on the fly.
|
112
|
+
# @param aSymbolName [String] the name of the grammar symbol to retrieve
|
113
|
+
# @return [NonTerminal]
|
114
|
+
def get_nonterminal(aSymbolName)
|
115
|
+
unless symbols.include? aSymbolName
|
116
|
+
symbols[aSymbolName] = NonTerminal.new(aSymbolName)
|
117
|
+
end
|
118
|
+
return symbols[aSymbolName]
|
119
|
+
end
|
120
|
+
|
110
121
|
end # class
|
111
122
|
end # module
|
112
123
|
end # module
|
@@ -45,17 +45,6 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
45
45
|
expect(subject.symbols['b']).to eq(b)
|
46
46
|
expect(subject.symbols['c']).to eq(c)
|
47
47
|
end
|
48
|
-
|
49
|
-
it 'should build non-terminals from their names' do
|
50
|
-
subject.add_non_terminals('PP', 'VP', 'DT')
|
51
|
-
expect(subject.symbols.size).to eq(3)
|
52
|
-
expect(subject.symbols['PP']).to be_kind_of(NonTerminal)
|
53
|
-
expect(subject.symbols['PP'].name).to eq('PP')
|
54
|
-
expect(subject.symbols['VP']).to be_kind_of(NonTerminal)
|
55
|
-
expect(subject.symbols['VP'].name).to eq('VP')
|
56
|
-
expect(subject.symbols['DT']).to be_kind_of(NonTerminal)
|
57
|
-
expect(subject.symbols['DT'].name).to eq('DT')
|
58
|
-
end
|
59
48
|
|
60
49
|
it 'should accept already built terminals' do
|
61
50
|
a = Terminal.new('a')
|
@@ -74,7 +63,6 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
74
63
|
subject do
|
75
64
|
instance = GrammarBuilder.new
|
76
65
|
instance.add_terminals('a', 'b', 'c')
|
77
|
-
instance.add_non_terminals('S', 'A')
|
78
66
|
instance
|
79
67
|
end
|
80
68
|
|
@@ -105,7 +93,6 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
105
93
|
subject do
|
106
94
|
instance = GrammarBuilder.new
|
107
95
|
instance.add_terminals('a', 'b', 'c')
|
108
|
-
instance.add_non_terminals('S', 'A')
|
109
96
|
instance.add_production('S' => ['A'])
|
110
97
|
instance.add_production('A' => %w(a A c))
|
111
98
|
instance.add_production('A' => ['b'])
|
@@ -128,11 +115,19 @@ module Rley # Open this namespace to avoid module qualifier prefixes
|
|
128
115
|
it 'should complain in absence of productions' do
|
129
116
|
instance = GrammarBuilder.new
|
130
117
|
instance.add_terminals('a', 'b', 'c')
|
131
|
-
instance.add_non_terminals('S', 'A')
|
132
118
|
err = StandardError
|
133
119
|
msg = 'No production found for grammar'
|
134
120
|
expect { instance.grammar }.to raise_error(err, msg)
|
135
121
|
end
|
122
|
+
|
123
|
+
it 'should complain when non-terminal has no production' do
|
124
|
+
instance = GrammarBuilder.new
|
125
|
+
instance.add_terminals('a', 'b', 'c')
|
126
|
+
instance.add_production('S' => ['A'])
|
127
|
+
err = StandardError
|
128
|
+
msg = 'Nonterminal A not rewritten'
|
129
|
+
expect { instance.grammar }.to raise_error(err, msg)
|
130
|
+
end
|
136
131
|
end
|
137
132
|
|
138
133
|
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.11
|
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-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|