Skip to content

Commit

Permalink
Added new minimal ParseDose using parslet
Browse files Browse the repository at this point in the history
  • Loading branch information
ngiger committed Apr 8, 2015
1 parent 810facb commit 0af2e93
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 16 deletions.
39 changes: 23 additions & 16 deletions Gemfile.lock
Expand Up @@ -5,6 +5,7 @@ PATH
archive-tar-minitar (~> 0.5.2)
mechanize (~> 2.5.1)
nokogiri (~> 1.5.10)
parslet (~> 1.7.0)
rubyXL (~> 3.3.1)
rubyzip (~> 1.1.3)
savon (~> 2.4.0)
Expand All @@ -14,11 +15,12 @@ PATH
GEM
remote: https://rubygems.org/
specs:
addressable (2.3.6)
addressable (2.3.8)
akami (1.2.2)
gyoku (>= 0.4.0)
nokogiri
archive-tar-minitar (0.5.2)
blankslate (3.1.3)
builder (3.2.2)
coderay (1.1.0)
columnize (0.9.0)
Expand All @@ -29,7 +31,7 @@ GEM
debugger-linecache (~> 1.2.0)
debugger-ruby_core_source (~> 1.3.5)
debugger-linecache (1.2.0)
debugger-ruby_core_source (1.3.7)
debugger-ruby_core_source (1.3.8)
diff-lcs (1.2.5)
domain_name (0.5.23)
unf (>= 0.0.5, < 1.0.0)
Expand All @@ -38,6 +40,7 @@ GEM
httpi (2.1.1)
rack
rubyntlm (~> 0.3.2)
json (1.8.2)
mechanize (2.5.1)
domain_name (~> 0.5, >= 0.5.1)
mime-types (~> 1.17, >= 1.17.2)
Expand All @@ -53,6 +56,8 @@ GEM
nokogiri (1.5.11)
nori (2.3.0)
ntlm-http (0.1.1)
parslet (1.7.0)
blankslate (>= 2.0, <= 4.0)
pry (0.10.1)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
Expand All @@ -63,20 +68,22 @@ GEM
rack (1.6.0)
rake (10.4.2)
rdoc (4.2.0)
rspec (3.1.0)
rspec-core (~> 3.1.0)
rspec-expectations (~> 3.1.0)
rspec-mocks (~> 3.1.0)
rspec-core (3.1.7)
rspec-support (~> 3.1.0)
rspec-expectations (3.1.2)
json (~> 1.4)
rspec (3.2.0)
rspec-core (~> 3.2.0)
rspec-expectations (~> 3.2.0)
rspec-mocks (~> 3.2.0)
rspec-core (3.2.3)
rspec-support (~> 3.2.0)
rspec-expectations (3.2.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.1.0)
rspec-mocks (3.1.3)
rspec-support (~> 3.1.0)
rspec-support (3.1.2)
rspec-support (~> 3.2.0)
rspec-mocks (3.2.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.2.0)
rspec-support (3.2.2)
ruby-ole (1.2.11.8)
rubyXL (3.3.6)
rubyXL (3.3.7)
nokogiri (>= 1.4.4)
rubyzip (>= 1.1.6)
rubyntlm (0.3.4)
Expand All @@ -93,7 +100,7 @@ GEM
sax-machine (0.1.0)
nokogiri (> 0.0.0)
slop (3.6.0)
spreadsheet (1.0.0)
spreadsheet (1.0.3)
ruby-ole (>= 1.0)
unf (0.1.4)
unf_ext
Expand All @@ -102,7 +109,7 @@ GEM
httpi (~> 2.0)
mime-types (< 2.0.0)
nokogiri (>= 1.4.0)
webmock (1.20.4)
webmock (1.21.0)
addressable (>= 2.3.6)
crack (>= 0.3.2)
webrobots (0.1.1)
Expand Down
91 changes: 91 additions & 0 deletions lib/oddb2xml/parslet_compositions.rb
@@ -0,0 +1,91 @@
# encoding: utf-8

# This file is shared since oddb2xml 2.0.0 (lib/oddb2xml/parse_compositions.rb)
# with oddb.org src/plugin/parse_compositions.rb
#
# It allows an easy parsing of the column P Zusammensetzung of the swissmedic packages.xlsx file
#

require 'parslet'
include Parslet

ParseComposition = Struct.new("ParseComposition", :source, :label, :label_description, :substances, :galenic_form, :route_of_administration)
ParseSubstance = Struct.new("ParseSubstance", :name, :qty, :unit, :chemical_substance, :chemical_qty, :chemical_unit, :is_active_agent, :dose, :cdose)

class CompositionsParser < Parslet::Parser

# Single character rules
rule(:lparen) { str('(') >> space? }
rule(:rparen) { str(')') >> space? }
rule(:comma) { str(',') >> space? }

rule(:space) { match('\s').repeat(1) }
rule(:space?) { space.maybe }

# Things
rule(:integer) { match('[0-9]').repeat(1).as(:int) >> space? }
rule(:identifier) { match['a-z'].repeat(1) }
rule(:operator) { match('[+]') >> space? }

# Grammar parts
rule(:sum) {
integer.as(:left) >> operator.as(:op) >> expression.as(:right) }
rule(:arglist) { expression >> (comma >> expression).repeat }
rule(:funcall) {
identifier.as(:funcall) >> lparen >> arglist.as(:arglist) >> rparen }

# dose
# rule(:qty) { integer }
rule(:dose) { integer.as(:qty) >> str('mg').as(:unit) }

rule(:expression) { dose }
#rule(:expression) { dose | funcall | sum | integer }
root :expression
end

class IntLit < Struct.new(:int)
def eval; int.to_i; end
end
class QtyLit < Struct.new(:qty)
def eval; qty.to_i; end
end
class Addition < Struct.new(:left, :right)
def eval; left.eval + right.eval; end
end
class FunCall < Struct.new(:name, :args);
def eval
p args.map { |s| s.eval }
end
end

class CompositionsTransformer < Parslet::Transform
rule(:int => simple(:int)) { IntLit.new(int) }
rule(
:left => simple(:left),
:right => simple(:right),
:op => '+') { Addition.new(left, right) }
rule(
:funcall => 'puts',
:arglist => subtree(:arglist)) { FunCall.new('puts', arglist) }
rule(
:qty => simple(:qty),
:unit => simple(:unit)) { ParseDose.new(qty, unit) }
end

class ParseDose
attr_reader :qty, :unit
def initialize(qty, unit)
@qty = qty.eval
@unit = unit.to_s
end
def eval
self
end
def ParseDose.from_string(string)
parser = CompositionsParser.new
transf = CompositionsTransformer.new
res = parser.parse(string)
transf.apply(parser.parse(string))
end
end

1 change: 1 addition & 0 deletions oddb2xml.gemspec
Expand Up @@ -28,6 +28,7 @@ Gem::Specification.new do |spec|
spec.add_dependency 'spreadsheet', '~> 1.0.0'
spec.add_dependency 'rubyXL', '~> 3.3.1'
spec.add_dependency 'sax-machine', '~> 0.1.0'
spec.add_dependency 'parslet', '~> 1.7.0'

spec.add_development_dependency "bundler"
spec.add_development_dependency "rake"
Expand Down
30 changes: 30 additions & 0 deletions spec/parslet_spec.rb
@@ -0,0 +1,30 @@
# encoding: utf-8

begin
require 'pry'
rescue LoadError
end
require 'pp'
require 'spec_helper'
require "#{Dir.pwd}/lib/oddb2xml/parslet_compositions"
require 'parslet/rig/rspec'

describe ParseDose do
RunAllTests = false
context 'should return correct dose for 123' do
# dose = ParseDose.from_string("123")
skip { expect(dose.qty).to eq 123 }
skip { expect(dose.unit).to eq nil }
end
context 'should return correct dose for mg' do
# dose = ParseDose.from_string('mg')
skip { expect(dose.qty).to eq 1.0 }
skip { expect(dose.unit).to eq 'mg' }
end

context 'should return correct dose for 2 mg' do
dose = ParseDose.from_string('2 mg')
specify { expect(dose.qty).to eq 2.0 }
specify { expect(dose.unit).to eq 'mg' }
end
end

0 comments on commit 0af2e93

Please sign in to comment.