bel_parser 1.0.0.alpha.13 → 1.0.0.alpha.14

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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/lib/bel_parser/language/apply_namespace_encoding.rb +5 -2
  4. data/lib/bel_parser/language/expression_validator.rb +25 -7
  5. data/lib/bel_parser/language/syntax/undefined_namespace_value.rb +5 -6
  6. data/lib/bel_parser/language.rb +8 -0
  7. data/lib/bel_parser/parsers/ast/node.rb +30 -3
  8. data/lib/bel_parser/parsers/bel_script/define_annotation.rb +1732 -1288
  9. data/lib/bel_parser/parsers/bel_script/set.rb +1424 -972
  10. data/lib/bel_parser/parsers/bel_script/set_document.rb +2735 -2100
  11. data/lib/bel_parser/parsers/common/list.rb +708 -462
  12. data/lib/bel_parser/parsers/common/list.rl +6 -4
  13. data/lib/bel_parser/resource/eager_reader.rb +9 -9
  14. data/lib/bel_parser/resource/http_cache.rb +26 -8
  15. data/lib/bel_parser/resource/resource_file_reader.rb +1 -0
  16. data/lib/bel_parser/resource/sparql_reader.rb +1 -0
  17. data/lib/bel_parser/script/state/annotation_definition.rb +62 -0
  18. data/lib/bel_parser/script/state/bel_version.rb +35 -0
  19. data/lib/bel_parser/script/state/document_property.rb +29 -0
  20. data/lib/bel_parser/script/state/namespace_definition.rb +32 -0
  21. data/lib/bel_parser/script/state/set.rb +57 -0
  22. data/lib/bel_parser/script/state/unset.rb +43 -0
  23. data/lib/bel_parser/script/state_function.rb +10 -0
  24. data/lib/bel_parser/script/syntax/expression_validation.rb +46 -0
  25. data/lib/bel_parser/script/syntax/invalid_regex_pattern.rb +49 -0
  26. data/lib/bel_parser/script/syntax/undefined_annotation.rb +60 -0
  27. data/lib/bel_parser/script/syntax/undefined_annotation_value.rb +83 -0
  28. data/lib/bel_parser/script/syntax/unresolvable_namespace.rb +55 -0
  29. data/lib/bel_parser/script/syntax/unsupported_bel_version.rb +58 -0
  30. data/lib/bel_parser/script/validator.rb +153 -0
  31. metadata +15 -1
@@ -25,9 +25,11 @@
25
25
 
26
26
  action append_list {
27
27
  # Append list argument if its value is not empty.
28
- list_arg_value = @buffers[:list_arg].children[0].children[0]
29
- if list_arg_value != ''
30
- @buffers[:list] <<= @buffers[:list_arg]
28
+ if @buffers[:list_arg]
29
+ list_arg_value = @buffers[:list_arg].children[0].children[0]
30
+ if list_arg_value != ''
31
+ @buffers[:list] <<= @buffers[:list_arg]
32
+ end
31
33
  end
32
34
  }
33
35
 
@@ -60,7 +62,7 @@
60
62
  (
61
63
  STRING %string $err(error_list_string) |
62
64
  IDENT %ident $err(error_list_ident)
63
- ) $err(append_list) %append_list
65
+ )? $err(append_list) %append_list
64
66
  SP*
65
67
  (
66
68
  ',' @clear
@@ -34,7 +34,7 @@ module BELParser
34
34
  return cached_concept if cached_concept
35
35
  end
36
36
 
37
- EMPTY_ARRAY
37
+ nil
38
38
  end
39
39
 
40
40
  def retrieve_values_from_resource(resource_identifier)
@@ -52,17 +52,17 @@ module BELParser
52
52
  if lock.try_lock
53
53
  Thread.new do
54
54
  value_hash = {
55
- :name => Hash.new { |hash, key| hash[key] = [] },
56
- :identifier => Hash.new { |hash, key| hash[key] = [] },
57
- :title => Hash.new { |hash, key| hash[key] = [] },
58
- :synonyms => Hash.new { |hash, key| hash[key] = [] }
55
+ :name => {},
56
+ :identifier => {},
57
+ :title => {},
58
+ :synonyms => {}
59
59
  }
60
60
  retrieve_values_from_resource(identifier).each do |concept|
61
- value_hash[:name][concept.name] << concept
62
- value_hash[:identifier][concept.identifier] << concept
63
- value_hash[:title][concept.title] << concept
61
+ value_hash[:name][concept.name] = concept
62
+ value_hash[:identifier][concept.identifier] = concept
63
+ value_hash[:title][concept.title] = concept
64
64
  concept.synonyms.each do |synonym|
65
- value_hash[:synonyms][synonym] << concept
65
+ value_hash[:synonyms][synonym] = concept
66
66
  end
67
67
  end
68
68
  resources[identifier] = value_hash
@@ -32,24 +32,42 @@ module BELParser
32
32
  end
33
33
  else
34
34
  uri = URI.parse(url)
35
- cached_file = File.open(cached_url_path, 'w')
36
35
  begin
37
36
  Net::HTTP.start(uri.host, uri.port) do |http|
38
37
  http.request(Net::HTTP::Get.new(uri)) do |response|
38
+
39
39
  if block_given?
40
- response.read_body do |chunk|
41
- cached_file.write(chunk)
42
- yield StringIO.new(chunk)
40
+ if response.is_a?(Net::HTTPOK)
41
+ cached_file = File.open(cached_url_path, 'w')
42
+ response.read_body do |chunk|
43
+ cached_file.write(chunk)
44
+ yield StringIO.new(chunk)
45
+ end
46
+ else
47
+ yield nil
43
48
  end
44
49
  else
45
- content = response.read_body
46
- cached_file.write(content)
47
- return StringIO.new(content)
50
+ if response.is_a?(Net::HTTPOK)
51
+ cached_file = File.open(cached_url_path, 'w')
52
+ content = response.read_body
53
+ cached_file.write(content)
54
+ return StringIO.new(content)
55
+ else
56
+ return nil
57
+ end
48
58
  end
49
59
  end
50
60
  end
61
+ rescue SocketError
62
+ if block_given?
63
+ yield nil
64
+ else
65
+ return nil
66
+ end
51
67
  ensure
52
- cached_file.close
68
+ if defined? cached_file
69
+ cached_file.close
70
+ end
53
71
  end
54
72
  end
55
73
  end
@@ -74,6 +74,7 @@ module BELParser
74
74
 
75
75
  def read_resource(url)
76
76
  io = @http_cache.get(url)
77
+ return nil unless io
77
78
 
78
79
  type, name, keyword, domain = nil
79
80
  io.each_line do |line|
@@ -60,6 +60,7 @@ module BELParser
60
60
  end
61
61
 
62
62
  def hash_to_concept_scheme(resource_identifier, hash)
63
+ return nil if hash[:types].value.empty?
63
64
  ConceptScheme.new(resource_identifier,
64
65
  *hash.values_at(:domain, :prefix, :prefLabel, :types))
65
66
  end
@@ -0,0 +1,62 @@
1
+ require 'bel_parser/language'
2
+ require 'bel_parser/quoting'
3
+ require 'bel_parser/parsers/ast/node'
4
+ require 'concurrent/hash'
5
+ require_relative '../state_function'
6
+
7
+ module BELParser
8
+ module Script
9
+ module State
10
+ class AnnotationDefinition
11
+ extend StateFunction
12
+ extend BELParser::Quoting
13
+
14
+ TARGET_NODE = BELParser::Parsers::AST::AnnotationDefinition
15
+
16
+ def self.consume(ast_node, script_context)
17
+ return nil unless ast_node.is_a?(TARGET_NODE)
18
+ resource_reader = script_context[:resource_reader]
19
+
20
+ keyword, domain = ast_node.children
21
+ prefix = keyword.identifier.string_literal
22
+ case
23
+ when domain.list?
24
+ handle_list(prefix, domain.child, script_context)
25
+ when domain.url?
26
+ handle_url(prefix, domain.child, script_context)
27
+ when domain.pattern?
28
+ handle_pattern(prefix, domain.child, script_context)
29
+ end
30
+ end
31
+
32
+ def self.handle_list(prefix, list_node, script_context)
33
+ script_context[:annotation_definitions] ||= Concurrent::Hash.new
34
+ script_context[:annotation_definitions][prefix] = [
35
+ :list,
36
+ list_node.list_items.map do |li|
37
+ unquote(li.children[0].string_literal)
38
+ end
39
+ ]
40
+ end
41
+ private_class_method :handle_list
42
+
43
+ def self.handle_pattern(prefix, pattern_node, script_context)
44
+ script_context[:annotation_definitions] ||= Concurrent::Hash.new
45
+ script_context[:annotation_definitions][prefix] = [
46
+ :pattern,
47
+ unquote(pattern_node.string)
48
+ ]
49
+ end
50
+ private_class_method :handle_pattern
51
+
52
+ def self.handle_url(prefix, url_node, script_context)
53
+ url = unquote(url_node.string.string_literal)
54
+ dataset = script_context[:resource_reader].retrieve_resource(url)
55
+ script_context[:annotation_definitions] ||= Concurrent::Hash.new
56
+ script_context[:annotation_definitions][prefix] = [:url, dataset]
57
+ end
58
+ private_class_method :handle_url
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,35 @@
1
+ require 'bel_parser/language'
2
+ require 'bel_parser/parsers/ast/node'
3
+ require 'bel_parser/quoting'
4
+ require 'concurrent/hash'
5
+ require_relative '../state_function'
6
+
7
+ module BELParser
8
+ module Script
9
+ module State
10
+ class BELVersion
11
+ extend StateFunction
12
+ extend BELParser::Quoting
13
+
14
+ TARGET_NODE = BELParser::Parsers::AST::DocumentProperty
15
+ BEL_VERSION_REGEX = /#{Regexp.escape('bel_version')}/i
16
+ DEFAULT_BEL_VERSION = '2.0'
17
+
18
+ def self.consume(ast_node, script_context)
19
+ return unless ast_node.is_a?(TARGET_NODE)
20
+ name, value = ast_node.children
21
+ name_string = name.identifier.string_literal
22
+ return unless name_string =~ BEL_VERSION_REGEX
23
+
24
+ value_string = unquote(value.children[0].string_literal)
25
+ begin
26
+ spec = BELParser::Language.specification(value_string)
27
+ rescue ArgumentError
28
+ spec = BELParser::Language.specification(DEFAULT_BEL_VERSION)
29
+ end
30
+ script_context[:specification] = spec
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ require 'bel_parser/parsers/ast/node'
2
+ require 'bel_parser/quoting'
3
+ require 'concurrent/hash'
4
+ require_relative '../state_function'
5
+
6
+ module BELParser
7
+ module Script
8
+ module State
9
+ class DocumentProperty
10
+ extend StateFunction
11
+ extend BELParser::Quoting
12
+
13
+ TARGET_NODE = BELParser::Parsers::AST::DocumentProperty
14
+
15
+ def self.consume(ast_node, script_context)
16
+ return nil unless ast_node.is_a?(TARGET_NODE)
17
+ hash = script_context[:document_properties] ||= Concurrent::Hash.new
18
+
19
+ name, value = ast_node.children
20
+ if name && value
21
+ name_string = name.identifier.string_literal
22
+ value_string = value.children[0].string_literal
23
+ hash[name_string] = unquote(value_string)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,32 @@
1
+ require 'bel_parser/language'
2
+ require 'bel_parser/quoting'
3
+ require 'bel_parser/parsers/ast/node'
4
+ require 'concurrent/hash'
5
+ require_relative '../state_function'
6
+
7
+ module BELParser
8
+ module Script
9
+ module State
10
+ class NamespaceDefinition
11
+ extend StateFunction
12
+ extend BELParser::Quoting
13
+
14
+ TARGET_NODE = BELParser::Parsers::AST::NamespaceDefinition
15
+
16
+ def self.consume(ast_node, script_context)
17
+ return nil unless ast_node.is_a?(TARGET_NODE)
18
+ resource_reader = script_context[:resource_reader]
19
+
20
+ keyword, domain = ast_node.children
21
+ if domain.url?
22
+ prefix = keyword.identifier.string_literal
23
+ url = unquote(domain.child.string.string_literal)
24
+ dataset = resource_reader.retrieve_resource(url)
25
+ script_context[:namespace_definitions] ||= Concurrent::Hash.new
26
+ script_context[:namespace_definitions][prefix] = dataset
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,57 @@
1
+ require 'bel_parser/language'
2
+ require 'bel_parser/quoting'
3
+ require 'bel_parser/parsers/ast/node'
4
+ require 'concurrent/hash'
5
+ require_relative '../state_function'
6
+
7
+ module BELParser
8
+ module Script
9
+ module State
10
+ class Set
11
+ extend StateFunction
12
+ extend BELParser::Quoting
13
+
14
+ TARGET_NODE = BELParser::Parsers::AST::Set
15
+ LIST_NODE = BELParser::Parsers::AST::List
16
+
17
+ def self.consume(ast_node, script_context)
18
+ return nil unless ast_node.is_a?(TARGET_NODE)
19
+ name, value = ast_node.children
20
+ name_string = name.identifier.string_literal
21
+ value_node = ast_node.value.children[0]
22
+ if value_node.is_a?(LIST_NODE)
23
+ value_node
24
+ .list_items.map { |li| li.children[0].string_literal }
25
+ .each do |string|
26
+ handle_annotation(name_string, string, script_context)
27
+ end
28
+ else
29
+ value_string = value_node.string_literal
30
+ case name_string
31
+ when /\ASTATEMENT_GROUP\Z/
32
+ handle_statement_group(value_string, script_context)
33
+ else
34
+ handle_annotation(name_string, value_string, script_context)
35
+ end
36
+ end
37
+ end
38
+
39
+ def self.handle_annotation(name, value, script_context)
40
+ # add to annotation state
41
+ script_context[:annotations] ||= Concurrent::Hash.new
42
+ script_context[:annotations][name] = value
43
+ end
44
+ private_class_method :handle_annotation
45
+
46
+ def self.handle_statement_group(value, script_context)
47
+ script_context[:statement_group] = value
48
+
49
+ # clear annotation state
50
+ script_context[:annotations] ||= Concurrent::Hash.new
51
+ script_context[:annotations].clear
52
+ end
53
+ private_class_method :handle_statement_group
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,43 @@
1
+ require 'bel_parser/language'
2
+ require 'bel_parser/quoting'
3
+ require 'bel_parser/parsers/ast/node'
4
+ require 'concurrent/hash'
5
+ require_relative '../state_function'
6
+
7
+ module BELParser
8
+ module Script
9
+ module State
10
+ class Unset
11
+ extend StateFunction
12
+ extend BELParser::Quoting
13
+
14
+ TARGET_NODE = BELParser::Parsers::AST::Unset
15
+
16
+ def self.consume(ast_node, script_context)
17
+ return nil unless ast_node.is_a?(TARGET_NODE)
18
+ name_string = ast_node.name.identifier.string_literal
19
+ case name_string
20
+ when /\ASTATEMENT_GROUP\Z/
21
+ handle_statement_group(script_context)
22
+ else
23
+ handle_annotation(name_string, script_context)
24
+ end
25
+ end
26
+
27
+ def self.handle_annotation(name, script_context)
28
+ script_context[:annotations] ||= Concurrent::Hash.new
29
+ script_context[:annotations].delete(name)
30
+ end
31
+ private_class_method :handle_annotation
32
+
33
+ def self.handle_statement_group(script_context)
34
+ script_context.delete(:statement_group)
35
+
36
+ script_context[:annotations] ||= Concurrent::Hash.new
37
+ script_context[:annotations].clear
38
+ end
39
+ private_class_method :handle_statement_group
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,10 @@
1
+ module BELParser
2
+ module Script
3
+ module StateFunction
4
+ # @abstract Extend {StateFunction} and override {#consume}.
5
+ def consume(ast_node, script_context)
6
+ raise NotImplementedError, "#{__method__} is not implemented."
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,46 @@
1
+ require 'bel_parser/language'
2
+ require 'bel_parser/language/expression_validator'
3
+ require 'bel_parser/language/syntax_function'
4
+ require 'bel_parser/language/syntax_warning'
5
+ require 'bel_parser/quoting'
6
+ require 'bel_parser/parsers/ast/node'
7
+ require 'concurrent/hash'
8
+
9
+ module BELParser
10
+ module Script
11
+ module Syntax
12
+ class ExpressionValidation
13
+ extend BELParser::Language::Syntax::SyntaxFunction
14
+ extend BELParser::Quoting
15
+
16
+ TARGET_NODES = [
17
+ BELParser::Parsers::AST::ObservedTerm,
18
+ BELParser::Parsers::AST::SimpleStatement,
19
+ BELParser::Parsers::AST::NestedStatement
20
+ ]
21
+ EXP_VALIDATOR = BELParser::Language::ExpressionValidator
22
+
23
+ def self.map(ast_node, script_context)
24
+ return nil unless TARGET_NODES.include?(ast_node.class)
25
+ return nil unless script_context.key?(:specification)
26
+
27
+ validator = expression_validator(script_context)
28
+ validator.validate(ast_node).select(&:failure?)
29
+ end
30
+
31
+ def self.expression_validator(script_context)
32
+ unless defined? @expression_validator
33
+ spec, namespaces, reader =
34
+ script_context
35
+ .values_at(
36
+ :specification,
37
+ :namespace_definitions,
38
+ :resource_reader)
39
+ @expression_validator = EXP_VALIDATOR.new(spec, namespaces, reader)
40
+ end
41
+ @expression_validator
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,49 @@
1
+ require 'bel_parser/language'
2
+ require 'bel_parser/language/syntax_function'
3
+ require 'bel_parser/language/syntax_error'
4
+ require 'bel_parser/quoting'
5
+ require 'bel_parser/parsers/ast/node'
6
+ require 'concurrent/hash'
7
+
8
+ module BELParser
9
+ module Script
10
+ module Syntax
11
+ class InvalidRegexPattern
12
+ extend BELParser::Language::Syntax::SyntaxFunction
13
+ extend BELParser::Quoting
14
+
15
+ TARGET_NODE = BELParser::Parsers::AST::Pattern
16
+
17
+ def self.map(ast_node, script_context)
18
+ return nil unless ast_node.is_a?(TARGET_NODE)
19
+ pattern = unquote(ast_node.string.string_literal)
20
+ begin
21
+ Regexp.new(pattern)
22
+ nil
23
+ rescue RegexpError => error
24
+ InvalidRegexPatternError.new(ast_node, pattern, error.to_s)
25
+ end
26
+ end
27
+ end
28
+
29
+ # InvalidRegexPattern indicates that a pattern represented an invalid
30
+ # regular expression.
31
+ class InvalidRegexPatternError < BELParser::Language::Syntax::SyntaxError
32
+ # Gets the invalid pattern.
33
+ attr_reader :pattern
34
+
35
+ def initialize(pattern_node, pattern, error_msg)
36
+ super(pattern_node, nil)
37
+ @pattern = pattern
38
+ @error_msg = error_msg
39
+ end
40
+
41
+ def msg
42
+ <<-MSG.gsub(/^ +/, '').delete("\n")
43
+ "#@pattern" is not a valid regular expression (#@error_msg).
44
+ MSG
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,60 @@
1
+ require 'bel_parser/language'
2
+ require 'bel_parser/language/syntax_function'
3
+ require 'bel_parser/language/syntax_error'
4
+ require 'bel_parser/quoting'
5
+ require 'bel_parser/parsers/ast/node'
6
+ require 'concurrent/hash'
7
+
8
+ module BELParser
9
+ module Script
10
+ module Syntax
11
+ class UndefinedAnnotation
12
+ extend BELParser::Language::Syntax::SyntaxFunction
13
+
14
+ TARGET_NODE = BELParser::Parsers::AST::Set
15
+ IMPLICIT_KEYWORDS = ['Citation', 'Evidence', 'STATEMENT_GROUP']
16
+
17
+ def self.map(ast_node, script_context)
18
+ return nil unless ast_node.is_a?(TARGET_NODE)
19
+ name_string = ast_node.name.identifier.string_literal
20
+ annotation_definitions =
21
+ script_context[:annotation_definitions] ||= Concurrent::Hash.new
22
+
23
+ return nil if IMPLICIT_KEYWORDS.include?(name_string)
24
+ return nil if annotation_definitions.key?(name_string)
25
+ UndefinedAnnotationError.new(
26
+ ast_node,
27
+ name_string,
28
+ script_context[:annotation_definitions])
29
+ end
30
+ end
31
+
32
+ # UndefinedAnnotationError represents an undefined annotation seen when
33
+ # checking a SET annotation.
34
+ class UndefinedAnnotationError < BELParser::Language::Syntax::SyntaxError
35
+ # Gets the undefined prefix.
36
+ attr_reader :prefix
37
+
38
+ def initialize(set_node, prefix, annotation_definitions)
39
+ super(set_node, nil)
40
+ @prefix = prefix
41
+ @annotation_definitions = annotation_definitions
42
+ end
43
+
44
+ def msg
45
+ defined_annotations =
46
+ if @annotation_definitions.empty?
47
+ 'No annotations are defined.'
48
+ else
49
+ annotation_prefixes = @annotation_definitions.keys.join(', ')
50
+ "Defined annotations: #{annotation_prefixes}"
51
+ end
52
+ <<-MSG.gsub(/^ +/, '').delete("\n")
53
+ Annotation definition is missing for "#@prefix".
54
+ #{defined_annotations}
55
+ MSG
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,83 @@
1
+ require 'bel_parser/language'
2
+ require 'bel_parser/language/syntax_function'
3
+ require 'bel_parser/language/syntax_warning'
4
+ require 'bel_parser/quoting'
5
+ require 'bel_parser/parsers/ast/node'
6
+ require 'concurrent/hash'
7
+
8
+ module BELParser
9
+ module Script
10
+ module Syntax
11
+ class UndefinedAnnotationValue
12
+ extend BELParser::Language::Syntax::SyntaxFunction
13
+ extend BELParser::Quoting
14
+
15
+ TARGET_NODE = BELParser::Parsers::AST::Set
16
+ LIST_NODE = BELParser::Parsers::AST::List
17
+ IMPLICIT_KEYWORDS = ['Citation', 'Evidence', 'STATEMENT_GROUP']
18
+
19
+ def self.map(ast_node, script_context)
20
+ return nil unless ast_node.is_a?(TARGET_NODE)
21
+ name, value = ast_node.children
22
+ name_string = ast_node.name.identifier.string_literal
23
+
24
+ return nil if IMPLICIT_KEYWORDS.include?(name_string)
25
+ dataset = annotation(name_string, script_context)
26
+ return nil unless dataset
27
+
28
+ rr = script_context[:resource_reader]
29
+ value_node = ast_node.value.children[0]
30
+ if value_node.is_a?(LIST_NODE)
31
+ value_node
32
+ .list_items.map { |li| li.children[0].string_literal }
33
+ .map do |string|
34
+ map_value(ast_node, name_string, string, dataset.identifier, rr)
35
+ end
36
+ else
37
+ map_value(
38
+ ast_node,
39
+ name_string,
40
+ value_node.string_literal,
41
+ dataset.identifier,
42
+ rr)
43
+ end
44
+ end
45
+
46
+ def self.annotation(name_string, script_context)
47
+ hash =
48
+ script_context[:annotation_definitions] ||= Concurrent::Hash.new
49
+ type, definition = hash[name_string]
50
+ type == :url ? definition : nil
51
+ end
52
+
53
+ def self.map_value(ast_node, name_string, value_string, identifier, rr)
54
+ value_string = unquote(value_string)
55
+ value = rr.retrieve_value_from_resource(identifier, value_string)
56
+ UndefinedAnnotationValueWarning.new(
57
+ ast_node,
58
+ name_string,
59
+ value_string) unless value
60
+ end
61
+ end
62
+
63
+ # UndefinedAnnotationValueWarning represents an undefined annotation value
64
+ # while checking a SET annotation.
65
+ class UndefinedAnnotationValueWarning < BELParser::Language::Syntax::SyntaxWarning
66
+ # Gets the prefix.
67
+ attr_reader :prefix
68
+ # Gets the undefined annotation value.
69
+ attr_reader :value
70
+
71
+ def initialize(set_node, prefix, value)
72
+ super(set_node, nil)
73
+ @prefix = prefix
74
+ @value = value
75
+ end
76
+
77
+ def msg
78
+ %(Undefined annotation value "#@value" for annotation "#@prefix".)
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end