bel_parser 1.0.0.alpha.2 → 1.0.0.alpha.3

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: 90ab686251113e217ed255a26b59b00aa9b6a947
4
- data.tar.gz: 87f55444534d215b579b4aec8d657cf38479ae1b
3
+ metadata.gz: fc1ced9daf61e6924edb4e15fe137e76fac85049
4
+ data.tar.gz: 1662c4c080eb06306ddc52a0c730bb226fe89e69
5
5
  SHA512:
6
- metadata.gz: 959bbb33f76a1888cabec4bc7bef6a00c130a45aeeac7a175e550403e2b14a78c9f75d147208e500a4aa400d5562e08d42a7733a6f53db38b688d0ba0c85a4e4
7
- data.tar.gz: 4c43a80f6ad4263753a5e49d76e6bbb57237a32cb61cb6af3dc8349a417ca2d049df3b18af9f1fddfedc3ff89b5e4bc2f7661b39a751aed790eae0dd596ef4b7
6
+ metadata.gz: 614db5a804a2ded6d9df1e93fe0a656fc033deccce4a20b649a52ead92eb18efc89900cbb3946f48faa97f29c0657b4c2190e7a987db0fc86b8c8ed9864356ee
7
+ data.tar.gz: 1d10d5b3a5605cd52ed3adde6998a0f6d0412c4f5008b71f818398e7f80e173348ac849f82b333c89ead3b1015fd75db5aff08fdf395f59198e60aabc43648a0
data/.gemspec CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
  'Anthony Bargnesi',
12
12
  'Nick Bargnesi',
13
13
  ]
14
- spec.date = %q{2016-04-08}
14
+ spec.date = %q{2016-04-11}
15
15
  spec.email = %q{abargnesi@selventa.com}
16
16
  spec.files = [
17
17
  Dir.glob('lib/**/*.{rb,rl}'),
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0.alpha.2
1
+ 1.0.0.alpha.3
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib'))
3
+
4
+ unless ARGV.first
5
+ program = File.basename($PROGRAM_NAME)
6
+ $stderr.puts <<-USAGE.gsub(/ {6}/, '')
7
+ usage: #{program} [BEL specification version] [PREFIX=URI]...
8
+ USAGE
9
+ exit 1
10
+ end
11
+ namespaces = Hash[ARGV[1..-1].map { |ns| ns.split('=') }]
12
+
13
+ require 'bel_parser'
14
+ require 'bel_parser/expression/term_validator'
15
+ BELParser::Expression::TermValidator.new(ARGV.first, namespaces).each($stdin) do |res|
16
+ res.each do |res|
17
+ puts " #{res}"
18
+ end
19
+ end
@@ -12,6 +12,8 @@ module BELParser
12
12
  include BELParser::Parsers::Expression
13
13
 
14
14
  FILTER = BELParser::ASTFilter.new(
15
+ :parameter,
16
+ :term,
15
17
  :statement_simple,
16
18
  :observed_term,
17
19
  :nested_statement
@@ -0,0 +1,50 @@
1
+ require_relative '../ast_filter'
2
+ require_relative '../ast_generator'
3
+ require_relative '../parsers/expression'
4
+ require_relative '../language'
5
+ require_relative '../language/expression_validator'
6
+
7
+ module BELParser
8
+ module Expression
9
+ # Parser for BEL Expression.
10
+ class TermValidator
11
+ include BELParser::Parsers::Common
12
+ include BELParser::Parsers::Expression
13
+
14
+ FILTER = BELParser::ASTFilter.new(:term)
15
+
16
+ def initialize(specification_version, namespaces)
17
+ @spec = BELParser::Language.specification(specification_version)
18
+ @validator = BELParser::Language::ExpressionValidator.new(@spec, namespaces)
19
+ end
20
+
21
+ def each(io)
22
+ if block_given?
23
+ filtered_ast = FILTER.each(BELParser::ASTGenerator.new.each(io))
24
+ filtered_ast.each do |results|
25
+ term = results.last.first
26
+ yield @validator.validate(term)
27
+ end
28
+ else
29
+ enum_for(:each, io)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ if __FILE__ == $PROGRAM_NAME
37
+ unless ARGV.first
38
+ program = File.basename($PROGRAM_NAME)
39
+ $stderr.puts <<-USAGE.gsub(/ {6}/, '')
40
+ usage: #{program} [BEL specification version] [PREFIX=URI]...
41
+ USAGE
42
+ exit 1
43
+ end
44
+ namespaces = Hash[ARGV[1..-1].map { |ns| ns.split('=') }]
45
+ BELParser::Expression::TermValidator.new(ARGV.first, namespaces).each($stdin) do |res|
46
+ res.each do |res|
47
+ puts " #{res}"
48
+ end
49
+ end
50
+ end
@@ -1,41 +1,31 @@
1
+ require_relative 'syntax'
2
+ require_relative 'semantics'
3
+
1
4
  module BELParser
2
5
  module Language
3
6
  class ExpressionValidator
4
- def initialize(spec)
5
- @spec = spec
7
+ def initialize(spec, namespaces)
8
+ @spec = spec
9
+ @namespaces = namespaces
10
+ @syntax_functions = Syntax.syntax_functions
6
11
  end
7
12
 
8
13
  def validate(expression_ast)
9
- node_errors = check_syntax(expression_ast)
10
- if !node_errors.empty?
11
- node_errors.each do |node_error|
12
- puts "Syntax error (#{node_error.syntax_errors}) with #{node_error.type}."
13
- end
14
- else
15
- check_semantics(expression_ast)
16
- end
14
+ syntax_problems = syntax(expression_ast)
15
+ return syntax_problems unless syntax_problems.empty?
16
+ [Syntax::Valid.new(expression_ast, @spec)] + semantics(expression_ast)
17
17
  end
18
18
 
19
19
  private
20
20
 
21
- def check_syntax(ast)
22
- # Clear syntax checks.
23
- ast.traverse.each do |node|
24
- node.syntax_errors.clear
25
- end
26
-
27
- # Run syntax checks, sets syntax_errors on nodes.
28
- @spec.syntax.each do |syntax|
29
- syntax.match(ast)
30
- end
31
-
32
- ast.traverse.select do |node|
33
- !node.syntax_errors.empty?
21
+ def syntax(expression_ast)
22
+ @syntax_functions.flat_map do |syntax_function|
23
+ syntax_function.map(expression_ast, @spec, @namespaces)
34
24
  end
35
25
  end
36
26
 
37
- def check_semantics(ast)
38
- BELParser::Language::Semantics.check_term(ast, @spec)
27
+ def semantics(expression_ast)
28
+ BELParser::Language::Semantics.check_term(expression_ast, @spec)
39
29
  end
40
30
  end
41
31
  end
@@ -0,0 +1,44 @@
1
+ require 'bel_parser/parsers/ast/node'
2
+
3
+ module BELParser
4
+ module Language
5
+ module Syntax
6
+ # InvalidFunction represents a syntax error with invalid function name
7
+ # according to a BEL specification.
8
+ class InvalidFunction
9
+ include SyntaxFunction
10
+
11
+ private_class_method :new
12
+
13
+ def self.map(expression_ast, spec, namespaces)
14
+ errors = []
15
+ expression_ast.traverse.map do |node|
16
+ next unless node.is_a?(BELParser::Parsers::AST::Function)
17
+ function_name = node.identifier.string_literal
18
+ unless spec.function(function_name.to_sym)
19
+ errors << InvalidFunctionSyntaxError.new(
20
+ expression_ast, spec, node, spec.functions)
21
+ end
22
+ end
23
+ errors
24
+ end
25
+ end
26
+
27
+ # InvalidFunctionSyntaxError indicates a function name was invalid.
28
+ class InvalidFunctionSyntaxError < SyntaxError
29
+ # Gets the functions defined by a BEL specification.
30
+ attr_reader :bel_functions
31
+
32
+ def initialize(expression_node, spec, error_node, bel_functions)
33
+ super(expression_node, spec, error_node)
34
+ @bel_functions = bel_functions
35
+ end
36
+
37
+ def msg
38
+ invalid_function = error_node.identifier.string_literal
39
+ %Q{Invalid function "#{invalid_function}".}
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,48 @@
1
+ require 'bel_parser/parsers/ast/node'
2
+
3
+ module BELParser
4
+ module Language
5
+ module Syntax
6
+ # Undefined namespace finds parameter prefixes that reference an
7
+ # undefined namespace.
8
+ class UndefinedNamespace
9
+ include SyntaxFunction
10
+
11
+ private_class_method :new
12
+
13
+ def self.map(expression_ast, spec, namespaces)
14
+ errors = []
15
+ expression_ast.traverse.map do |node|
16
+ next unless node.is_a?(BELParser::Parsers::AST::Prefix)
17
+ next if node.identifier.nil?
18
+
19
+ namespace_prefix = node.identifier.string_literal
20
+ unless namespaces[namespace_prefix]
21
+ errors << UndefinedNamespaceError.new(
22
+ expression_ast, node, namespaces)
23
+ end
24
+ end
25
+ errors
26
+ end
27
+ end
28
+
29
+ # UndefinedNamespaceError indicates a parameter prefix is referencing
30
+ # an undefined namespace.
31
+ class UndefinedNamespaceError < SyntaxError
32
+ # Gets the defined namespaces.
33
+ attr_reader :defined_namespaces
34
+
35
+ def initialize(expression_node, spec, error_node, defined_namespaces)
36
+ super(expression_node, spec, error_node)
37
+ @defined_namespaces = defined_namespaces.dup
38
+ end
39
+
40
+ def msg
41
+ undefined_namespace = error_node.identifier.string_literal
42
+ %Q{Undefined namespace "#{undefined_namespace}".}
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+
@@ -0,0 +1,33 @@
1
+ require_relative 'syntax_function'
2
+ require_relative 'syntax_error'
3
+ require_relative 'syntax_warning'
4
+
5
+ module BELParser
6
+ module Language
7
+ module Syntax
8
+ def self.syntax_functions
9
+ self.constants.collect do |symbol|
10
+ const = self.const_get(symbol)
11
+ const if
12
+ const.respond_to?(:include?) &&
13
+ const.include?(SyntaxFunction)
14
+ end.compact
15
+ end
16
+
17
+ class Valid < SyntaxResult
18
+ def msg
19
+ 'Syntax is valid.'
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ # Require all generic syntax functions.
27
+ Dir[
28
+ File.join(
29
+ File.dirname(File.expand_path(__FILE__)),
30
+ 'syntax', '*.rb')
31
+ ].each do |path|
32
+ require_relative "syntax/#{File.basename(path)}"
33
+ end
@@ -0,0 +1,25 @@
1
+ require_relative 'syntax_result'
2
+
3
+ module BELParser
4
+ module Language
5
+ module Syntax
6
+ class SyntaxError < SyntaxResult
7
+ attr_reader :expression_node, :target_node
8
+
9
+ def initialize(expression_node, specification, target_node)
10
+ super(expression_node, specification)
11
+ @target_node = target_node
12
+ end
13
+
14
+ # @abstract Subclass and override {#msg} to provide the message.
15
+ def msg
16
+ raise NotImplementedError, "#{__method__} is not implemented."
17
+ end
18
+
19
+ def to_s
20
+ "Error: #{msg}"
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,13 @@
1
+ module BELParser
2
+ module Language
3
+ module Syntax
4
+ module SyntaxFunction
5
+ # @abstract Include {SyntaxFunction} and override {#map} to check
6
+ # expression syntax.
7
+ def self.map(expression_ast, spec, namespaces)
8
+ raise NotImplementedError, "#{__method__} is not implemented."
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,23 @@
1
+ module BELParser
2
+ module Language
3
+ module Syntax
4
+ class SyntaxResult
5
+ attr_reader :expression_node, :specification
6
+
7
+ def initialize(expression_node, specification)
8
+ @expression_node = expression_node
9
+ @specification = specification
10
+ end
11
+
12
+ # @abstract Subclass and override {#msg} to provide the message.
13
+ def msg
14
+ raise NotImplementedError, "#{__method__} is not implemented."
15
+ end
16
+
17
+ def to_s
18
+ "Info: #{msg}"
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,20 @@
1
+ require_relative 'syntax_result'
2
+
3
+ module BELParser
4
+ module Language
5
+ module Syntax
6
+ class SyntaxWarning < SyntaxResult
7
+ attr_reader :expression_node, :target_node
8
+
9
+ def initialize(expression_node, specification, target_node)
10
+ super(expression_node, specification)
11
+ @target_node = target_node
12
+ end
13
+
14
+ def to_s
15
+ "Warning: #{msg}"
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,5 +1,6 @@
1
1
  require_relative 'language/function'
2
2
  require_relative 'language/quoting'
3
+ require_relative 'language/syntax'
3
4
  require_relative 'language/semantics'
4
5
  require_relative 'language/signature'
5
6
  require_relative 'language/specification'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bel_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.alpha.2
4
+ version: 1.0.0.alpha.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anthony Bargnesi
@@ -9,12 +9,12 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-04-08 00:00:00.000000000 Z
12
+ date: 2016-04-11 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Implements language versions 1.0 and 2.0.
15
15
  email: abargnesi@selventa.com
16
16
  executables:
17
- - bel2_termcheck
17
+ - bel2_validator
18
18
  extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
@@ -23,13 +23,13 @@ files:
23
23
  - LICENSE
24
24
  - README.md
25
25
  - VERSION
26
- - bin/bel2_termcheck
26
+ - bin/bel2_validator
27
27
  - lib/bel_parser.rb
28
28
  - lib/bel_parser/ast_filter.rb
29
29
  - lib/bel_parser/ast_generator.rb
30
30
  - lib/bel_parser/ast_validator.rb
31
31
  - lib/bel_parser/expression/parser.rb
32
- - lib/bel_parser/expression/term_semantics.rb
32
+ - lib/bel_parser/expression/term_validator.rb
33
33
  - lib/bel_parser/language.rb
34
34
  - lib/bel_parser/language/expression_validator.rb
35
35
  - lib/bel_parser/language/function.rb
@@ -42,6 +42,12 @@ files:
42
42
  - lib/bel_parser/language/signature.rb
43
43
  - lib/bel_parser/language/specification.rb
44
44
  - lib/bel_parser/language/syntax.rb
45
+ - lib/bel_parser/language/syntax/invalid_function.rb
46
+ - lib/bel_parser/language/syntax/undefined_namespace.rb
47
+ - lib/bel_parser/language/syntax_error.rb
48
+ - lib/bel_parser/language/syntax_function.rb
49
+ - lib/bel_parser/language/syntax_result.rb
50
+ - lib/bel_parser/language/syntax_warning.rb
45
51
  - lib/bel_parser/language/version1_0.rb
46
52
  - lib/bel_parser/language/version1_0/functions/abundance.rb
47
53
  - lib/bel_parser/language/version1_0/functions/biological_process.rb
data/bin/bel2_termcheck DELETED
@@ -1,39 +0,0 @@
1
- #!/usr/bin/env ruby
2
- $:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib'))
3
-
4
- require 'bel_parser'
5
- require 'bel_parser/language/version2_0'
6
- require 'bel_parser/language/semantics/analyzer'
7
-
8
- module BELParser
9
- module Expression
10
- # Parser for BEL Expression.
11
- class TermSemanticsParser
12
- include BELParser::Parsers::Common
13
- include BELParser::Parsers::Expression
14
-
15
- FILTER = BELParser::ASTFilter.new(:term)
16
-
17
- def each(io)
18
- if block_given?
19
- v2 = BELParser::Language::Version2_0::Specification.new
20
- filtered_ast = FILTER.each(BELParser::ASTGenerator.new.each(io))
21
- filtered_ast.each do |results|
22
- term = results.last.first
23
- yield BELParser::Language::Semantics.check_term(term, v2)
24
- end
25
- else
26
- enum_for(:each, io)
27
- end
28
- end
29
- end
30
- end
31
- end
32
-
33
- BELParser::Expression::TermSemanticsParser.new.each($stdin) do |signature|
34
- valid_signatures = signature.compact
35
- puts 'Signatures:'
36
- valid_signatures.each do |sig|
37
- puts " #{sig}"
38
- end
39
- end
@@ -1,36 +0,0 @@
1
- require_relative '../ast_filter'
2
- require_relative '../ast_generator'
3
- require_relative '../parsers/expression'
4
- require_relative '../language/version2_0'
5
- require_relative '../language/semantics/analyzer'
6
-
7
- module BELParser
8
- module Expression
9
- # Parser for BEL Expression.
10
- class TermSemanticsParser
11
- include BELParser::Parsers::Common
12
- include BELParser::Parsers::Expression
13
-
14
- FILTER = BELParser::ASTFilter.new(:term)
15
-
16
- def each(io)
17
- if block_given?
18
- v2 = BELParser::Language::Version2_0::Specification.new
19
- filtered_ast = FILTER.each(BELParser::ASTGenerator.new.each(io))
20
- filtered_ast.each do |results|
21
- term = results.last.first
22
- yield BELParser::Language::Semantics.check_term(term, v2)
23
- end
24
- else
25
- enum_for(:each, io)
26
- end
27
- end
28
- end
29
- end
30
- end
31
-
32
- if __FILE__ == $PROGRAM_NAME
33
- BELParser::Expression::TermSemanticsParser.new.each($stdin) do |semantics|
34
- puts semantics.join(", ")
35
- end
36
- end