nlg_xml_realiser_builder 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0b9ac3b073d046a5716db912bcf9f8ec79db54a3
4
+ data.tar.gz: 3c16b1dd32d8e05c292d37a188d319b220e55bd5
5
+ SHA512:
6
+ metadata.gz: fd217f950e9663fed67e2582b0f1d2339d4e14950018846ed0ae8aa22a5a27915c2c8e9ce8c946dd6cc9a1b2896a6f2e83d77c08ed46448146b818954252bfae
7
+ data.tar.gz: dc76fcfeeb3cc22dd13bf3287cc299a225c3e22c13343bfff52acea1816dcc56a54bda68caf24d955da0deffe486575ce0a3014d7b4072a6b2c341f458385afb
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.1
5
+ before_install: gem install bundler -v 1.13.1
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in nlg_xml_realiser_builder.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,165 @@
1
+ GNU LESSER GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+
9
+ This version of the GNU Lesser General Public License incorporates
10
+ the terms and conditions of version 3 of the GNU General Public
11
+ License, supplemented by the additional permissions listed below.
12
+
13
+ 0. Additional Definitions.
14
+
15
+ As used herein, "this License" refers to version 3 of the GNU Lesser
16
+ General Public License, and the "GNU GPL" refers to version 3 of the GNU
17
+ General Public License.
18
+
19
+ "The Library" refers to a covered work governed by this License,
20
+ other than an Application or a Combined Work as defined below.
21
+
22
+ An "Application" is any work that makes use of an interface provided
23
+ by the Library, but which is not otherwise based on the Library.
24
+ Defining a subclass of a class defined by the Library is deemed a mode
25
+ of using an interface provided by the Library.
26
+
27
+ A "Combined Work" is a work produced by combining or linking an
28
+ Application with the Library. The particular version of the Library
29
+ with which the Combined Work was made is also called the "Linked
30
+ Version".
31
+
32
+ The "Minimal Corresponding Source" for a Combined Work means the
33
+ Corresponding Source for the Combined Work, excluding any source code
34
+ for portions of the Combined Work that, considered in isolation, are
35
+ based on the Application, and not on the Linked Version.
36
+
37
+ The "Corresponding Application Code" for a Combined Work means the
38
+ object code and/or source code for the Application, including any data
39
+ and utility programs needed for reproducing the Combined Work from the
40
+ Application, but excluding the System Libraries of the Combined Work.
41
+
42
+ 1. Exception to Section 3 of the GNU GPL.
43
+
44
+ You may convey a covered work under sections 3 and 4 of this License
45
+ without being bound by section 3 of the GNU GPL.
46
+
47
+ 2. Conveying Modified Versions.
48
+
49
+ If you modify a copy of the Library, and, in your modifications, a
50
+ facility refers to a function or data to be supplied by an Application
51
+ that uses the facility (other than as an argument passed when the
52
+ facility is invoked), then you may convey a copy of the modified
53
+ version:
54
+
55
+ a) under this License, provided that you make a good faith effort to
56
+ ensure that, in the event an Application does not supply the
57
+ function or data, the facility still operates, and performs
58
+ whatever part of its purpose remains meaningful, or
59
+
60
+ b) under the GNU GPL, with none of the additional permissions of
61
+ this License applicable to that copy.
62
+
63
+ 3. Object Code Incorporating Material from Library Header Files.
64
+
65
+ The object code form of an Application may incorporate material from
66
+ a header file that is part of the Library. You may convey such object
67
+ code under terms of your choice, provided that, if the incorporated
68
+ material is not limited to numerical parameters, data structure
69
+ layouts and accessors, or small macros, inline functions and templates
70
+ (ten or fewer lines in length), you do both of the following:
71
+
72
+ a) Give prominent notice with each copy of the object code that the
73
+ Library is used in it and that the Library and its use are
74
+ covered by this License.
75
+
76
+ b) Accompany the object code with a copy of the GNU GPL and this license
77
+ document.
78
+
79
+ 4. Combined Works.
80
+
81
+ You may convey a Combined Work under terms of your choice that,
82
+ taken together, effectively do not restrict modification of the
83
+ portions of the Library contained in the Combined Work and reverse
84
+ engineering for debugging such modifications, if you also do each of
85
+ the following:
86
+
87
+ a) Give prominent notice with each copy of the Combined Work that
88
+ the Library is used in it and that the Library and its use are
89
+ covered by this License.
90
+
91
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
92
+ document.
93
+
94
+ c) For a Combined Work that displays copyright notices during
95
+ execution, include the copyright notice for the Library among
96
+ these notices, as well as a reference directing the user to the
97
+ copies of the GNU GPL and this license document.
98
+
99
+ d) Do one of the following:
100
+
101
+ 0) Convey the Minimal Corresponding Source under the terms of this
102
+ License, and the Corresponding Application Code in a form
103
+ suitable for, and under terms that permit, the user to
104
+ recombine or relink the Application with a modified version of
105
+ the Linked Version to produce a modified Combined Work, in the
106
+ manner specified by section 6 of the GNU GPL for conveying
107
+ Corresponding Source.
108
+
109
+ 1) Use a suitable shared library mechanism for linking with the
110
+ Library. A suitable mechanism is one that (a) uses at run time
111
+ a copy of the Library already present on the user's computer
112
+ system, and (b) will operate properly with a modified version
113
+ of the Library that is interface-compatible with the Linked
114
+ Version.
115
+
116
+ e) Provide Installation Information, but only if you would otherwise
117
+ be required to provide such information under section 6 of the
118
+ GNU GPL, and only to the extent that such information is
119
+ necessary to install and execute a modified version of the
120
+ Combined Work produced by recombining or relinking the
121
+ Application with a modified version of the Linked Version. (If
122
+ you use option 4d0, the Installation Information must accompany
123
+ the Minimal Corresponding Source and Corresponding Application
124
+ Code. If you use option 4d1, you must provide the Installation
125
+ Information in the manner specified by section 6 of the GNU GPL
126
+ for conveying Corresponding Source.)
127
+
128
+ 5. Combined Libraries.
129
+
130
+ You may place library facilities that are a work based on the
131
+ Library side by side in a single library together with other library
132
+ facilities that are not Applications and are not covered by this
133
+ License, and convey such a combined library under terms of your
134
+ choice, if you do both of the following:
135
+
136
+ a) Accompany the combined library with a copy of the same work based
137
+ on the Library, uncombined with any other library facilities,
138
+ conveyed under the terms of this License.
139
+
140
+ b) Give prominent notice with the combined library that part of it
141
+ is a work based on the Library, and explaining where to find the
142
+ accompanying uncombined form of the same work.
143
+
144
+ 6. Revised Versions of the GNU Lesser General Public License.
145
+
146
+ The Free Software Foundation may publish revised and/or new versions
147
+ of the GNU Lesser General Public License from time to time. Such new
148
+ versions will be similar in spirit to the present version, but may
149
+ differ in detail to address new problems or concerns.
150
+
151
+ Each version is given a distinguishing version number. If the
152
+ Library as you received it specifies that a certain numbered version
153
+ of the GNU Lesser General Public License "or any later version"
154
+ applies to it, you have the option of following the terms and
155
+ conditions either of that published version or of any later version
156
+ published by the Free Software Foundation. If the Library as you
157
+ received it does not specify a version number of the GNU Lesser
158
+ General Public License, you may choose any version of the GNU Lesser
159
+ General Public License ever published by the Free Software Foundation.
160
+
161
+ If the Library as you received it specifies that a proxy can decide
162
+ whether future versions of the GNU Lesser General Public License shall
163
+ apply, that proxy's public statement of acceptance of any version is
164
+ permanent authorization for you to choose that version for the
165
+ Library.
data/README.md ADDED
@@ -0,0 +1,198 @@
1
+ # Simple NLG compatible XML Realiser Builder
2
+
3
+ This is still not a full featured builder for Simple NLG but the goal is to make it easier to compose the XML Realiser recordings.
4
+
5
+ There is an online service at https://nlg-service.herokuapp.com which embeds SimpleNLG in a web service.
6
+
7
+ Check out [nlg-service](https://github.com/Codeminer42/nlg_service) to see the Rails-API running under JRuby.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'nlg_xml_realiser_builder'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install nlg_xml_realiser_builder
24
+
25
+ ## Usage
26
+
27
+ The XML Realiser format can be checked through it's [XML Schema](https://github.com/simplenlg/simplenlg/blob/master/src/main/resources/xml/RealizerSchema.xsd) which is roughly implemented in this DSL, with most of the relevant attributes validations as well.
28
+
29
+ The usage is mainly nesting the main builder elements:
30
+
31
+ * Sentence-like Phrase - SPhraseSpec - `sp(tag, options, &block)`
32
+ * Noun Phrase - NPPhraseSpec - `np(tag, noun, options, &block)`
33
+ * Verb Phrase - VPPhraseSpec - `vp(tag, verb, options, &block)`
34
+ * Adjective Phrase - AdjPhraseSpec - `adj(tag, adjective, options, &block)`
35
+ * Adverbial Phrase - AdvPhraseSpec - `adv(tag, adverb, options, &block)`
36
+ * Propositional Phrase - PPPhraseSpec - `pp(tag, preposition, options, &block)`
37
+ * Coordination between 2 or more phrases - CoordinatedPhraseElement - `cp(tag, options, &block)`
38
+
39
+ Example:
40
+
41
+ ```
42
+ dsl = NlgXmlRealiserBuilder::DSL.new
43
+ dsl.builder(true) do
44
+ sp :child do
45
+ subj :np, 'there', cat: 'ADVERB'
46
+ verb 'be' do
47
+ compl [ 'a', 'restenosis' ] do
48
+ preMod :cp, conj: ',' do
49
+ coord :adj, 'eccentric'
50
+ coord :adj, 'tubular'
51
+ end
52
+ postMod :str, '(18 mm x 1 mm)'
53
+ end
54
+ postMod :pp, 'from' do
55
+ preMod :vp, 'extend', FORM: 'GERUND'
56
+ compl ['the'] do
57
+ preMod :adj, 'proximal'
58
+ end
59
+ postMod :pp, 'to' do
60
+ compl [ 'a', 'right coronary artery' ] do
61
+ preMod :adj, 'mid'
62
+ end
63
+ end
64
+ end
65
+ postMod :pp, 'with' do
66
+ compl :np, 'TIMI 1 flow'
67
+ end
68
+ end
69
+ end
70
+ end.to_xml
71
+ ```
72
+
73
+ Resulting XML:
74
+
75
+ ```
76
+ <?xml version="1.0"?>
77
+ <NLGSpec xmlns="http://simplenlg.googlecode.com/svn/trunk/res/xml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
78
+ <Recording>
79
+ <Record>
80
+ <Document cat="PARAGRAPH">
81
+ <child xsi:type="SPhraseSpec">
82
+ <subj xsi:type="NPPhraseSpec">
83
+ <head cat="ADVERB">
84
+ <base>there</base>
85
+ </head>
86
+ </subj>
87
+ <vp xsi:type="VPPhraseSpec">
88
+ <head cat="VERB">
89
+ <base>be</base>
90
+ </head>
91
+ <compl xsi:type="NPPhraseSpec">
92
+ <head cat="NOUN">
93
+ <base>restenosis</base>
94
+ </head>
95
+ <spec cat="DETERMINER">
96
+ <base>a</base>
97
+ </spec>
98
+ <preMod xsi:type="CoordinatedPhraseElement" conj=",">
99
+ <coord xsi:type="AdjPhraseSpec">
100
+ <head cat="ADJECTIVE">
101
+ <base>eccentric</base>
102
+ </head>
103
+ </coord>
104
+ <coord xsi:type="AdjPhraseSpec">
105
+ <head cat="ADJECTIVE">
106
+ <base>tubular</base>
107
+ </head>
108
+ </coord>
109
+ </preMod>
110
+ <postMod xsi:type="StringElement">
111
+ <val>(18 mm x 1 mm)</val>
112
+ </postMod>
113
+ </compl>
114
+ <postMod xsi:type="PPPhraseSpec">
115
+ <head cat="PREPOSITION">
116
+ <base>from</base>
117
+ </head>
118
+ <preMod xsi:type="VPPhraseSpec" FORM="GERUND">
119
+ <head cat="VERB">
120
+ <base>extend</base>
121
+ </head>
122
+ </preMod>
123
+ <compl xsi:type="NPPhraseSpec">
124
+ <spec cat="DETERMINER">
125
+ <base>the</base>
126
+ </spec>
127
+ <preMod xsi:type="AdjPhraseSpec">
128
+ <head cat="ADJECTIVE">
129
+ <base>proximal</base>
130
+ </head>
131
+ </preMod>
132
+ </compl>
133
+ <postMod xsi:type="PPPhraseSpec">
134
+ <head cat="PREPOSITION">
135
+ <base>to</base>
136
+ </head>
137
+ <compl xsi:type="NPPhraseSpec">
138
+ <head cat="NOUN">
139
+ <base>right coronary artery</base>
140
+ </head>
141
+ <spec cat="DETERMINER">
142
+ <base>a</base>
143
+ </spec>
144
+ <preMod xsi:type="AdjPhraseSpec">
145
+ <head cat="ADJECTIVE">
146
+ <base>mid</base>
147
+ </head>
148
+ </preMod>
149
+ </compl>
150
+ </postMod>
151
+ </postMod>
152
+ <postMod xsi:type="PPPhraseSpec">
153
+ <head cat="PREPOSITION">
154
+ <base>with</base>
155
+ </head>
156
+ <compl xsi:type="NPPhraseSpec">
157
+ <head cat="NOUN">
158
+ <base>TIMI 1 flow</base>
159
+ </head>
160
+ </compl>
161
+ </postMod>
162
+ </vp>
163
+ </child>
164
+ </Document>
165
+ </Record>
166
+ </Recording>
167
+ </NLGSpec>
168
+ ```
169
+
170
+ From here you can use the [NLG Service Web Service](https://github.com/Codeminer42/nlg_service) to transform this XML into a grammatically and ortographically correct natural English phrase.
171
+
172
+ ## Development
173
+
174
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
175
+
176
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
177
+
178
+ You can use the NLG Web Service from the `bin/console` using:
179
+
180
+ ```
181
+ NlgXmlRealiserBuilder.test_post(builder.to_xml)
182
+ ```
183
+
184
+ It should return a properly realised English phrase.
185
+
186
+
187
+ ## Contributing
188
+
189
+ Bug reports and pull requests are welcome on GitHub at https://github.com/Codeminer42/nlg_xml_realiser_builder.
190
+
191
+
192
+ ## License
193
+
194
+ Author: Fabio Akita
195
+ Copyright 2016 (C) Codeminer 42
196
+
197
+ The gem is available as open source under the terms of the [LGPL-3.0 License](https://opensource.org/licenses/LGPL-3.0).
198
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "nlg_xml_realiser_builder"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,17 @@
1
+ require "nlg_xml_realiser_builder/version"
2
+ require "nlg_xml_realiser_builder/consts"
3
+ require "nlg_xml_realiser_builder/primitive_operations"
4
+ require "nlg_xml_realiser_builder/phrase_specs"
5
+ require "nlg_xml_realiser_builder/porcelain"
6
+ require "nlg_xml_realiser_builder/dsl"
7
+ require "nokogiri"
8
+ require "net/http"
9
+ require "uri"
10
+
11
+ module NlgXmlRealiserBuilder
12
+ def self.test_post(text)
13
+ uri = URI.parse("#{ENV['SERVICE_URL'] || 'http://nlg-service.herokuapp.com'}/api/realiser")
14
+ response = Net::HTTP.post_form(uri, {"xml" => text})
15
+ response.body.strip
16
+ end
17
+ end
@@ -0,0 +1,225 @@
1
+ # frozen_string_literal: true
2
+ module NlgXmlRealiserBuilder
3
+ module Consts
4
+ XML_SCHEMA = {
5
+ 'xmlns' => 'http://simplenlg.googlecode.com/svn/trunk/res/xml',
6
+ 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
7
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance'}.freeze
8
+
9
+ SPEC_METHODS = %i(sp np vp adj adv cp pp str)
10
+
11
+ DOCUMENT_CATEGORIES = %w(DOCUMENT
12
+ SECTION
13
+ PARAGRAPH
14
+ SENTENCE
15
+ LIST
16
+ ENUMERATED_LIST
17
+ LIST_ITEM).freeze
18
+
19
+ PHRASE_SPEC_TYPES = %w(SPhraseSpec
20
+ VPPhraseSpec
21
+ NPPhraseSpec
22
+ AdjPhraseSpec
23
+ AdvPhraseSpec
24
+ PPPhraseSpec
25
+ CoordinatedPhraseElement
26
+ PhraseElement
27
+ StringElement
28
+ WordElement).freeze
29
+
30
+ # What elements does each phrase spec type accepts
31
+
32
+ DOCUMENTELEMENT_ELEMENTS = %i(child).freeze
33
+ SPHRASESPEC_ELEMENTS = %i(cuePhrase subj vp).freeze
34
+ PHRASE_ELEMENTS = %i(frontMod preMod compl postMod head).freeze
35
+ COORDINATEDPHRASEELEMENT_ELEMENTS = %i(coord).freeze
36
+
37
+ VPPHRASESPEC_ELEMENTS = PHRASE_ELEMENTS
38
+ NPPHRASESPEC_ELEMENTS = ( PHRASE_ELEMENTS + [ :spec ] ).freeze
39
+ ADJPHRASESPEC_ELEMENTS = PHRASE_ELEMENTS
40
+ ADVPHRASESPEC_ELEMENTS = PHRASE_ELEMENTS
41
+ PPPHRASESPEC_ELEMENTS = PHRASE_ELEMENTS
42
+
43
+ # What attributes does each phrase spec type accepts
44
+
45
+ SPHRASESPEC_ATTRIBUTES = %i(AGGREGATE_AUXILIARY
46
+ CLAUSE_STATUS
47
+ COMPLEMENTISER
48
+ FORM
49
+ INTERROGATIVE_TYPE
50
+ MODAL
51
+ NEGATED
52
+ PASSIVE
53
+ PERFECT
54
+ PERSON
55
+ PROGRESSIVE
56
+ SUPPRESS_GENITIVE_IN_GERUND
57
+ SUPRESSED_COMPLEMENTISER
58
+ TENSE).freeze
59
+
60
+ VPPHRASESPEC_ATTRIBUTES = %i(AGGREGATE_AUXILIARY
61
+ FORM
62
+ MODAL
63
+ NEGATED
64
+ PASSIVE
65
+ PERFECT
66
+ PERSON
67
+ PROGRESSIVE
68
+ SUPPRESS_GENITIVE_IN_GERUND
69
+ SUPRESSED_COMPLEMENTISER
70
+ TENSE).freeze
71
+
72
+ NPPHRASESPEC_ATTRIBUTES = %i(ADJECTIVE_ORDERING
73
+ ELIDED
74
+ NUMBER
75
+ GENDER
76
+ PERSON
77
+ POSSESSIVE
78
+ PRONOMINAL
79
+ cat
80
+ discourseFunction
81
+ appositive).freeze
82
+
83
+ ADJPHRASESPEC_ATTRIBUTES = %i(IS_COMPARATIVE IS_SUPERLATIVE).freeze
84
+
85
+ ADVPHRASESPEC_ATTRIBUTES = [].freeze
86
+
87
+ PPPHRASESPEC_ATTRIBUTES = [].freeze
88
+
89
+ COORDINATEDPHRASEELEMENT_ATTRIBUTES = %i(conj
90
+ cat
91
+ APPOSITIVE
92
+ CONJUNCTION_TYPE
93
+ MODAL
94
+ NEGATED
95
+ NUMBER
96
+ PERSON
97
+ POSSESSIVE
98
+ PROGRESSIVE
99
+ RAISE_SPECIFIER
100
+ SUPRESSED_COMPLEMENTISER
101
+ TENSE).freeze
102
+
103
+ WORDELEMENT_ATTRIBUTES = %i(cat
104
+ id
105
+ EXPLETIVE_SUBJECT
106
+ PROPER
107
+ var
108
+ canned).freeze
109
+
110
+ # What primitive values does each kind of attribute accepts
111
+
112
+ NLG_PHRASE_CATEGORY = %w(CLAUSE
113
+ ADJECTIVE_PHRASE
114
+ ADVERB_PHRASE
115
+ NOUN_PHRASE
116
+ PREPOSITIONAL_PHRASE
117
+ VERB_PHRASE
118
+ CANNED_TEXT).freeze
119
+
120
+ NLG_LEXICAL_CATEGORY = %w(ANY
121
+ SYMBOL
122
+ NOUN
123
+ ADJECTIVE
124
+ ADVERB
125
+ VERB
126
+ DETERMINER
127
+ PRONOUN
128
+ CONJUNCTION
129
+ PREPOSITION
130
+ COMPLEMENTISER
131
+ MODAL
132
+ AUXILIARY).freeze
133
+
134
+ NLG_TENSE = %w(FUTURE PAST PRESENT).freeze
135
+
136
+ NLG_CLAUSE_STATUS = %w(MATRIX SUBORDINATE).freeze
137
+
138
+ NLG_DISCOURSE_FUNCTION = %w(AUXILIARY
139
+ COMPLEMENT
140
+ CONJUNCTION
141
+ CUE_PHRASE
142
+ FRONT_MODIFIER
143
+ HEAD
144
+ INDIRECT_OBJECT
145
+ OBJECT
146
+ PRE_MODIFIER
147
+ POST_MODIFIER
148
+ SPECIFIER
149
+ SUBJECT
150
+ VERB_PHRASE).freeze
151
+
152
+ NLG_FORM = %w(BARE_INFINITIVE
153
+ GERUND
154
+ IMPERATIVE
155
+ INFINITIVE
156
+ NORMAL
157
+ PAST_PARTICIPLE
158
+ PRESENT_PARTICIPLE).freeze
159
+
160
+ NLG_GENDER = %w(MASCULINE FEMININE NEUTER).freeze
161
+
162
+ NLG_NUMBER_AGREEMENT = %w(BOTH PLURAL SINGULAR).freeze
163
+
164
+ NLG_PERSON = %w(FIRST SECOND THIRD).freeze
165
+
166
+ NLG_INTERROGATIVE_TYPE = %w(HOW
167
+ WHAT_OBJECT
168
+ WHAT_SUBJECT
169
+ WHERE
170
+ WHO_INDIRECT_OBJECT
171
+ WHO_OBJECT
172
+ WHO_SUBJECT
173
+ WHY
174
+ YES_NO).freeze
175
+
176
+ NLG_INFLECTION = %w(GRECO_LATIN_REGULAR
177
+ IRREGULAR
178
+ REGULAR
179
+ REGULAR_DOUBLE
180
+ UNCOUNT
181
+ INVARIANT).freeze
182
+
183
+ NLG_BOOLEAN = [true, false].freeze
184
+
185
+ ATTRIBUTES = {
186
+ ADJECTIVE_ORDERING: NLG_BOOLEAN,
187
+ AGGREGATE_AUXILIARY: NLG_BOOLEAN,
188
+ APPOSITIVE: NLG_BOOLEAN,
189
+ CLAUSE_STATUS: NLG_CLAUSE_STATUS,
190
+ COMPLEMENTISER: String,
191
+ CONJUNCTION_TYPE: String,
192
+ ELIDED: NLG_BOOLEAN,
193
+ EXPLETIVE_SUBJECT: NLG_BOOLEAN,
194
+ FORM: NLG_FORM,
195
+ GENDER: NLG_GENDER,
196
+ INTERROGATIVE_TYPE: NLG_INTERROGATIVE_TYPE,
197
+ IS_COMPARATIVE: NLG_BOOLEAN,
198
+ IS_SUPERLATIVE: NLG_BOOLEAN,
199
+ MODAL: String,
200
+ NEGATED: NLG_BOOLEAN,
201
+ NUMBER: NLG_NUMBER_AGREEMENT,
202
+ PASSIVE: NLG_BOOLEAN,
203
+ PERFECT: NLG_BOOLEAN,
204
+ PERSON: NLG_PERSON,
205
+ POSSESSIVE: NLG_BOOLEAN,
206
+ PROGRESSIVE: NLG_BOOLEAN,
207
+ PRONOMINAL: NLG_BOOLEAN,
208
+ PROPER: NLG_BOOLEAN,
209
+ RAISE_SPECIFIER: NLG_BOOLEAN,
210
+ SUPPRESS_GENITIVE_IN_GERUND: NLG_BOOLEAN,
211
+ SUPRESSED_COMPLEMENTISER: NLG_BOOLEAN,
212
+ TENSE: NLG_TENSE,
213
+ appositive: NLG_BOOLEAN,
214
+ base: String,
215
+ canned: NLG_BOOLEAN,
216
+ cat: ( NLG_PHRASE_CATEGORY + NLG_LEXICAL_CATEGORY ).freeze,
217
+ conj: String,
218
+ discourseFunction: NLG_DISCOURSE_FUNCTION,
219
+ id: String,
220
+ val: String,
221
+ var: NLG_INFLECTION,
222
+ }.freeze
223
+
224
+ end
225
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+ module NlgXmlRealiserBuilder
3
+ class DSL
4
+ include NlgXmlRealiserBuilder::PrimitiveOperations
5
+ include NlgXmlRealiserBuilder::PhraseSpecs
6
+ include NlgXmlRealiserBuilder::Porcelain
7
+ end
8
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+ module NlgXmlRealiserBuilder
3
+ module PhraseSpecs
4
+ SPEC_METHODS = %i(sp np vp adj adv cp pp)
5
+
6
+ def sp(tag = :child, options = {}, &block)
7
+ abstract_spec('SPhraseSpec', tag, options, block)
8
+ end
9
+
10
+ def np(tag = :subj, noun = nil, options = {}, &block)
11
+ determiner = options.delete(:determiner)
12
+ cat = options.delete(:cat) || 'NOUN'
13
+ determiner, noun = noun if noun.is_a?(Array)
14
+
15
+ abstract_spec('NPPhraseSpec', tag, options, block) do
16
+ head(noun, cat) if noun
17
+ spec(determiner) if determiner
18
+ end
19
+ end
20
+
21
+ def vp(tag = :vp, verb = nil, options = {}, &block)
22
+ abstract_spec('VPPhraseSpec', tag, options, block) do
23
+ head(verb, 'VERB') if verb
24
+ end
25
+ end
26
+
27
+ def adj(tag = :coord, adjective = nil, options = {}, &block)
28
+ abstract_spec('AdjPhraseSpec', tag, options, block) do
29
+ head(adjective, 'ADJECTIVE') if adjective
30
+ end
31
+ end
32
+
33
+ def adv(tag = :coord, adverb = nil, options = {}, &block)
34
+ abstract_spec('AdvPhraseSpec', tag, options, block) do
35
+ head(adjective, 'ADVERB') if adjective
36
+ end
37
+ end
38
+
39
+ def cp(tag = :vp, options = { conj: ',' }, &block)
40
+ abstract_spec('CoordinatedPhraseElement', tag, options, block)
41
+ end
42
+
43
+ def pp(tag = :compl, preposition = nil, options = {}, &block)
44
+ abstract_spec('PPPhraseSpec', tag, options, block) do
45
+ head(preposition, 'PREPOSITION') if preposition
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+ module NlgXmlRealiserBuilder
3
+ module Porcelain
4
+ def list(enumerated: false, &block)
5
+ document_category = enumerated ? 'ENUMERATED_LIST' : 'LIST'
6
+ doc(:Document, cat: document_category, &block)
7
+ end
8
+
9
+ def item(&block)
10
+ doc(:child, cat: 'LIST_ITEM', &block)
11
+ end
12
+
13
+ def verb(verb = nil, options = {}, &block)
14
+ vp(:vp, verb, options, &block)
15
+ end
16
+
17
+ # Invert the tag for the phrase spec
18
+ private def abstract_tag(spec_method, tag = nil, main_value = nil, options = {}, &block)
19
+ unless Consts::SPEC_METHODS.include?(spec_method)
20
+ raise "spec method #{spec_method} not included in [#{Consts::SPEC_METHODS.join(", ")}]"
21
+ end
22
+ if main_value.is_a?(Hash)
23
+ send(spec_method, tag, main_value, &block) # case of 'cp' which has no main value parameter
24
+ else
25
+ send(spec_method, tag, main_value, options, &block)
26
+ end
27
+ end
28
+
29
+ # Create inverted methods so instead of doing:
30
+ #
31
+ # np(:compl, ['an', 'apple'])
32
+ #
33
+ # we can do:
34
+ #
35
+ # compl(:np, ['an', 'apple'])
36
+ #
37
+ (Consts::DOCUMENTELEMENT_ELEMENTS + Consts::SPHRASESPEC_ELEMENTS + Consts::PHRASE_ELEMENTS + Consts::COORDINATEDPHRASEELEMENT_ELEMENTS).each do |main_tag|
38
+ next if %i(head vp).include? main_tag
39
+ module_eval <<-EOF
40
+ def #{main_tag}(spec_method, main_value = nil, options = {}, &block)
41
+ if spec_method.is_a?(Array)
42
+ abstract_tag(:np, :#{main_tag}, spec_method, main_value || {}, &block)
43
+ else
44
+ abstract_tag(spec_method, :#{main_tag}, main_value, options, &block)
45
+ end
46
+ end
47
+ EOF
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+ module NlgXmlRealiserBuilder
3
+ module PrimitiveOperations
4
+ def builder(simple = false, &block)
5
+ Nokogiri::XML::Builder.new do |xml|
6
+ @xml = xml
7
+ xml.NLGSpec(Consts::XML_SCHEMA) {
8
+ xml.Recording {
9
+ if simple
10
+ record {
11
+ doc {
12
+ instance_eval(&block) if block
13
+ }
14
+ }
15
+ else
16
+ instance_eval(&block) if block
17
+ end
18
+ }
19
+ }
20
+ end
21
+ end
22
+
23
+ def record(name = nil, &block)
24
+ attributes = {}
25
+ attributes.merge!(name: name) if name
26
+ @xml.Record(attributes) {
27
+ instance_eval(&block) if block
28
+ }
29
+ end
30
+
31
+ def doc(tag = :Document, options = {}, &block)
32
+ category = options.delete(:cat) || 'PARAGRAPH'
33
+ unless Consts::DOCUMENT_CATEGORIES.include?(category)
34
+ raise "Document category '#{category}' is not in [#{Consts::DOCUMENT_CATEGORIES.join(", ")}]"
35
+ end
36
+ attributes = {}
37
+ attributes.merge!('xsi:type' => 'DocumentElement') unless tag == :Document
38
+ attributes.merge!('cat' => category)
39
+ @xml.send(tag, attributes) {
40
+ nlg_eval('DocumentElement', &block)
41
+ }
42
+ end
43
+
44
+ def str(tag = :compl, val = nil, options = nil, &block)
45
+ return unless val
46
+ @xml.send(tag, 'xsi:type' => 'StringElement') {
47
+ @xml.val val.to_s
48
+ }
49
+ end
50
+
51
+ def head(base, cat = 'NOUN')
52
+ unless Consts::NLG_LEXICAL_CATEGORY.include?(cat)
53
+ raise "Head category '#{cat}' is not in [#{Consts::NLG_LEXICAL_CATEGORY.join(", ")}]"
54
+ end
55
+ @xml.head('cat' => cat) {
56
+ @xml.base base
57
+ }
58
+ end
59
+
60
+ def spec(base, cat = 'DETERMINER')
61
+ unless Consts::NLG_LEXICAL_CATEGORY.include?(cat)
62
+ raise "Specifier category must be in [#{Consts::NLG_LEXICAL_CATEGORY.join(", ")}]"
63
+ end
64
+ @xml.spec_('xsi:type' => 'WordElement', 'cat' => cat) {
65
+ @xml.base base
66
+ }
67
+ end
68
+
69
+ private def nlg_eval(spec_type, &block)
70
+ begin
71
+ previous_call, @last_call = @last_call, spec_type
72
+ instance_eval(&block) if block
73
+ ensure
74
+ @last_call = previous_call
75
+ end
76
+ end
77
+
78
+ private def validate_element!(tag)
79
+ elements = Consts.const_get("#{@last_call.upcase}_ELEMENTS".to_sym)
80
+ unless elements.include?(tag)
81
+ raise "Element #{tag} is now allowed within #{@last_call}. Must be in [#{elements.join(', ')}]"
82
+ end
83
+ end
84
+
85
+ private def validate_spec_type!(spec_type)
86
+ unless Consts::PHRASE_SPEC_TYPES.include?(spec_type)
87
+ raise "There is no '#{spec_type}' in [#{Consts::PHRASE_SPEC_TYPES.join(", ")}]"
88
+ end
89
+ end
90
+
91
+ private def is_attribute_valid?(value, validation)
92
+ validation.is_a?(Array) ? validation.include?(value) : value.is_a?(validation)
93
+ end
94
+
95
+ private def validate_attributes!(options = {}, spec_type)
96
+ valid_attributes = Consts.const_get("#{spec_type.upcase}_ATTRIBUTES")
97
+ invalid_attributes = options.keys - valid_attributes
98
+ unless invalid_attributes.empty?
99
+ raise "Attributes [#{invalid_attributes.join(", ")}] are invalid for #{spec_type} which only allows [#{valid_attributes.join(", ")}]"
100
+ end
101
+
102
+ results = options.keys.reject { |key|
103
+ is_attribute_valid?( options[key], Consts::ATTRIBUTES[key] )
104
+ }.reduce([]) { |key|
105
+ results << "Attribute #{key} with value '#{options[key]}' should be in [#{Consts::ATTRIBUTES[key].join(", ")}]"
106
+ }
107
+
108
+ raise results.join("\n") unless results.empty?
109
+ end
110
+
111
+ private def abstract_spec(spec_type, tag, options = {}, block)
112
+ validate_element! tag
113
+ validate_spec_type! spec_type
114
+ validate_attributes! options, spec_type
115
+
116
+ attributes = { 'xsi:type' => spec_type }
117
+ attributes.merge!(options) if options && !options.empty?
118
+
119
+ @xml.send(tag, attributes) {
120
+ yield if block_given?
121
+ nlg_eval(spec_type, &block)
122
+ }
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,3 @@
1
+ module NlgXmlRealiserBuilder
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'nlg_xml_realiser_builder/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "nlg_xml_realiser_builder"
8
+ spec.version = NlgXmlRealiserBuilder::VERSION
9
+ spec.authors = ["Fabio Akita"]
10
+ spec.email = ["boss@akitaonrails.com"]
11
+
12
+ spec.summary = %q{Builder for Simple NLG XML format}
13
+ spec.description = %q{Builds Simple NLG compatible XML recordings}
14
+ spec.homepage = "https://github.com/Codeminer42/nlg_xml_realiser_builder"
15
+ spec.license = "LGPL"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.13"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rspec", "~> 3.0"
27
+ spec.add_development_dependency "pry", "~> 0.10.4"
28
+
29
+ spec.add_runtime_dependency "nokogiri", "~> 1.6.8.1"
30
+ end
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nlg_xml_realiser_builder
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Fabio Akita
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-10-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.13'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.13'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.10.4
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.10.4
69
+ - !ruby/object:Gem::Dependency
70
+ name: nokogiri
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 1.6.8.1
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 1.6.8.1
83
+ description: Builds Simple NLG compatible XML recordings
84
+ email:
85
+ - boss@akitaonrails.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - ".travis.yml"
93
+ - Gemfile
94
+ - LICENSE.txt
95
+ - README.md
96
+ - Rakefile
97
+ - bin/console
98
+ - bin/setup
99
+ - lib/nlg_xml_realiser_builder.rb
100
+ - lib/nlg_xml_realiser_builder/consts.rb
101
+ - lib/nlg_xml_realiser_builder/dsl.rb
102
+ - lib/nlg_xml_realiser_builder/phrase_specs.rb
103
+ - lib/nlg_xml_realiser_builder/porcelain.rb
104
+ - lib/nlg_xml_realiser_builder/primitive_operations.rb
105
+ - lib/nlg_xml_realiser_builder/version.rb
106
+ - nlg_xml_realiser_builder.gemspec
107
+ homepage: https://github.com/Codeminer42/nlg_xml_realiser_builder
108
+ licenses:
109
+ - LGPL
110
+ metadata: {}
111
+ post_install_message:
112
+ rdoc_options: []
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ requirements: []
126
+ rubyforge_project:
127
+ rubygems_version: 2.5.1
128
+ signing_key:
129
+ specification_version: 4
130
+ summary: Builder for Simple NLG XML format
131
+ test_files: []