bel_parser 1.0.0.alpha.1
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 +7 -0
- data/.gemspec +28 -0
- data/CHANGELOG.md +10 -0
- data/LICENSE +191 -0
- data/README.md +9 -0
- data/VERSION +1 -0
- data/bin/bel2_termcheck +39 -0
- data/lib/bel_parser.rb +17 -0
- data/lib/bel_parser/ast_filter.rb +27 -0
- data/lib/bel_parser/ast_generator.rb +86 -0
- data/lib/bel_parser/ast_validator.rb +40 -0
- data/lib/bel_parser/expression/parser.rb +42 -0
- data/lib/bel_parser/expression/term_semantics.rb +36 -0
- data/lib/bel_parser/language.rb +7 -0
- data/lib/bel_parser/language/function.rb +59 -0
- data/lib/bel_parser/language/quoting.rb +236 -0
- data/lib/bel_parser/language/semantic_ast.rb +604 -0
- data/lib/bel_parser/language/semantics/analyzer.rb +59 -0
- data/lib/bel_parser/language/signature.rb +39 -0
- data/lib/bel_parser/language/specification.rb +49 -0
- data/lib/bel_parser/language/syntax/expression/incomplete_node.rb +14 -0
- data/lib/bel_parser/language/syntax/expression/invalid_term_function.rb +22 -0
- data/lib/bel_parser/language/version1.rb +50 -0
- data/lib/bel_parser/language/version1/functions/abundance.rb +85 -0
- data/lib/bel_parser/language/version1/functions/biological_process.rb +85 -0
- data/lib/bel_parser/language/version1/functions/catalytic_activity.rb +110 -0
- data/lib/bel_parser/language/version1/functions/cell_secretion.rb +80 -0
- data/lib/bel_parser/language/version1/functions/cell_surface_expression.rb +80 -0
- data/lib/bel_parser/language/version1/functions/chaperone_activity.rb +110 -0
- data/lib/bel_parser/language/version1/functions/complex_abundance.rb +115 -0
- data/lib/bel_parser/language/version1/functions/composite_abundance.rb +80 -0
- data/lib/bel_parser/language/version1/functions/degradation.rb +80 -0
- data/lib/bel_parser/language/version1/functions/fusion.rb +302 -0
- data/lib/bel_parser/language/version1/functions/gene_abundance.rb +125 -0
- data/lib/bel_parser/language/version1/functions/gtp_bound_activity.rb +110 -0
- data/lib/bel_parser/language/version1/functions/kinase_activity.rb +110 -0
- data/lib/bel_parser/language/version1/functions/list.rb +115 -0
- data/lib/bel_parser/language/version1/functions/micro_rna_abundance.rb +85 -0
- data/lib/bel_parser/language/version1/functions/molecular_activity.rb +80 -0
- data/lib/bel_parser/language/version1/functions/pathology.rb +85 -0
- data/lib/bel_parser/language/version1/functions/peptidase_activity.rb +110 -0
- data/lib/bel_parser/language/version1/functions/phosphatase_activity.rb +110 -0
- data/lib/bel_parser/language/version1/functions/products.rb +80 -0
- data/lib/bel_parser/language/version1/functions/protein_abundance.rb +245 -0
- data/lib/bel_parser/language/version1/functions/protein_modification.rb +167 -0
- data/lib/bel_parser/language/version1/functions/reactants.rb +80 -0
- data/lib/bel_parser/language/version1/functions/reaction.rb +85 -0
- data/lib/bel_parser/language/version1/functions/ribosylation_activity.rb +110 -0
- data/lib/bel_parser/language/version1/functions/rna_abundance.rb +125 -0
- data/lib/bel_parser/language/version1/functions/substitution.rb +96 -0
- data/lib/bel_parser/language/version1/functions/transcriptional_activity.rb +110 -0
- data/lib/bel_parser/language/version1/functions/translocation.rb +100 -0
- data/lib/bel_parser/language/version1/functions/transport_activity.rb +110 -0
- data/lib/bel_parser/language/version1/functions/truncation.rb +82 -0
- data/lib/bel_parser/language/version1/return_types/abundance.rb +20 -0
- data/lib/bel_parser/language/version1/return_types/any.rb +74 -0
- data/lib/bel_parser/language/version1/return_types/biological_process.rb +17 -0
- data/lib/bel_parser/language/version1/return_types/catalytic_activity.rb +20 -0
- data/lib/bel_parser/language/version1/return_types/chaperone_activity.rb +20 -0
- data/lib/bel_parser/language/version1/return_types/complex_abundance.rb +17 -0
- data/lib/bel_parser/language/version1/return_types/fusion.rb +17 -0
- data/lib/bel_parser/language/version1/return_types/gene_abundance.rb +17 -0
- data/lib/bel_parser/language/version1/return_types/gtp_bound_activity.rb +20 -0
- data/lib/bel_parser/language/version1/return_types/kinase_activity.rb +20 -0
- data/lib/bel_parser/language/version1/return_types/list.rb +17 -0
- data/lib/bel_parser/language/version1/return_types/micro_rna_abundance.rb +17 -0
- data/lib/bel_parser/language/version1/return_types/molecular_activity.rb +20 -0
- data/lib/bel_parser/language/version1/return_types/pathology.rb +17 -0
- data/lib/bel_parser/language/version1/return_types/peptidase_activity.rb +20 -0
- data/lib/bel_parser/language/version1/return_types/phosphatase_activity.rb +20 -0
- data/lib/bel_parser/language/version1/return_types/products.rb +17 -0
- data/lib/bel_parser/language/version1/return_types/protein_abundance.rb +17 -0
- data/lib/bel_parser/language/version1/return_types/protein_modification.rb +17 -0
- data/lib/bel_parser/language/version1/return_types/reactants.rb +17 -0
- data/lib/bel_parser/language/version1/return_types/ribosylation_activity.rb +20 -0
- data/lib/bel_parser/language/version1/return_types/rna_abundance.rb +17 -0
- data/lib/bel_parser/language/version1/return_types/substitution.rb +17 -0
- data/lib/bel_parser/language/version1/return_types/transcriptional_activity.rb +20 -0
- data/lib/bel_parser/language/version1/return_types/transport_activity.rb +20 -0
- data/lib/bel_parser/language/version1/return_types/truncation.rb +17 -0
- data/lib/bel_parser/language/version2.rb +50 -0
- data/lib/bel_parser/language/version2/functions/abundance.rb +165 -0
- data/lib/bel_parser/language/version2/functions/activity.rb +115 -0
- data/lib/bel_parser/language/version2/functions/biological_process.rb +85 -0
- data/lib/bel_parser/language/version2/functions/cell_secretion.rb +80 -0
- data/lib/bel_parser/language/version2/functions/cell_surface_expression.rb +80 -0
- data/lib/bel_parser/language/version2/functions/complex_abundance.rb +190 -0
- data/lib/bel_parser/language/version2/functions/composite_abundance.rb +80 -0
- data/lib/bel_parser/language/version2/functions/degradation.rb +80 -0
- data/lib/bel_parser/language/version2/functions/fragment.rb +119 -0
- data/lib/bel_parser/language/version2/functions/from_location.rb +85 -0
- data/lib/bel_parser/language/version2/functions/fusion.rb +227 -0
- data/lib/bel_parser/language/version2/functions/gene_abundance.rb +195 -0
- data/lib/bel_parser/language/version2/functions/list.rb +115 -0
- data/lib/bel_parser/language/version2/functions/location.rb +85 -0
- data/lib/bel_parser/language/version2/functions/micro_rna_abundance.rb +165 -0
- data/lib/bel_parser/language/version2/functions/molecular_activity.rb +83 -0
- data/lib/bel_parser/language/version2/functions/pathology.rb +85 -0
- data/lib/bel_parser/language/version2/functions/products.rb +80 -0
- data/lib/bel_parser/language/version2/functions/protein_abundance.rb +285 -0
- data/lib/bel_parser/language/version2/functions/protein_modification.rb +167 -0
- data/lib/bel_parser/language/version2/functions/reactants.rb +80 -0
- data/lib/bel_parser/language/version2/functions/reaction.rb +85 -0
- data/lib/bel_parser/language/version2/functions/rna_abundance.rb +195 -0
- data/lib/bel_parser/language/version2/functions/to_location.rb +85 -0
- data/lib/bel_parser/language/version2/functions/translocation.rb +90 -0
- data/lib/bel_parser/language/version2/functions/variant.rb +83 -0
- data/lib/bel_parser/language/version2/return_types/abundance.rb +20 -0
- data/lib/bel_parser/language/version2/return_types/activity.rb +20 -0
- data/lib/bel_parser/language/version2/return_types/any.rb +74 -0
- data/lib/bel_parser/language/version2/return_types/biological_process.rb +17 -0
- data/lib/bel_parser/language/version2/return_types/complex_abundance.rb +17 -0
- data/lib/bel_parser/language/version2/return_types/fragment.rb +20 -0
- data/lib/bel_parser/language/version2/return_types/from_location.rb +20 -0
- data/lib/bel_parser/language/version2/return_types/fusion.rb +17 -0
- data/lib/bel_parser/language/version2/return_types/gene_abundance.rb +17 -0
- data/lib/bel_parser/language/version2/return_types/list.rb +17 -0
- data/lib/bel_parser/language/version2/return_types/location.rb +20 -0
- data/lib/bel_parser/language/version2/return_types/micro_rna_abundance.rb +17 -0
- data/lib/bel_parser/language/version2/return_types/molecular_activity.rb +20 -0
- data/lib/bel_parser/language/version2/return_types/pathology.rb +17 -0
- data/lib/bel_parser/language/version2/return_types/products.rb +17 -0
- data/lib/bel_parser/language/version2/return_types/protein_abundance.rb +17 -0
- data/lib/bel_parser/language/version2/return_types/protein_modification.rb +17 -0
- data/lib/bel_parser/language/version2/return_types/reactants.rb +17 -0
- data/lib/bel_parser/language/version2/return_types/rna_abundance.rb +17 -0
- data/lib/bel_parser/language/version2/return_types/to_location.rb +20 -0
- data/lib/bel_parser/language/version2/return_types/variant.rb +20 -0
- data/lib/bel_parser/mixin/line_continuator.rb +15 -0
- data/lib/bel_parser/mixin/line_mapping.rb +14 -0
- data/lib/bel_parser/parser.rb +54 -0
- data/lib/bel_parser/parsers/ast/mapped_traversal.rb +36 -0
- data/lib/bel_parser/parsers/ast/node.rb +705 -0
- data/lib/bel_parser/parsers/ast/sexp.rb +8 -0
- data/lib/bel_parser/parsers/ast/traversal.rb +21 -0
- data/lib/bel_parser/parsers/bel_script.rb +4 -0
- data/lib/bel_parser/parsers/bel_script/define_annotation.rb +5476 -0
- data/lib/bel_parser/parsers/bel_script/define_annotation.rl +141 -0
- data/lib/bel_parser/parsers/bel_script/define_namespace.rb +1780 -0
- data/lib/bel_parser/parsers/bel_script/define_namespace.rl +121 -0
- data/lib/bel_parser/parsers/bel_script/set.rb +4556 -0
- data/lib/bel_parser/parsers/bel_script/set.rl +116 -0
- data/lib/bel_parser/parsers/bel_script/unset.rb +706 -0
- data/lib/bel_parser/parsers/bel_script/unset.rl +95 -0
- data/lib/bel_parser/parsers/common.rb +5 -0
- data/lib/bel_parser/parsers/common/blank_line.rb +211 -0
- data/lib/bel_parser/parsers/common/blank_line.rl +81 -0
- data/lib/bel_parser/parsers/common/comment_line.rb +245 -0
- data/lib/bel_parser/parsers/common/comment_line.rl +97 -0
- data/lib/bel_parser/parsers/common/common.rb +7 -0
- data/lib/bel_parser/parsers/common/common.rl +13 -0
- data/lib/bel_parser/parsers/common/identifier.rb +289 -0
- data/lib/bel_parser/parsers/common/identifier.rl +106 -0
- data/lib/bel_parser/parsers/common/list.rb +2142 -0
- data/lib/bel_parser/parsers/common/list.rl +144 -0
- data/lib/bel_parser/parsers/common/string.rb +271 -0
- data/lib/bel_parser/parsers/common/string.rl +107 -0
- data/lib/bel_parser/parsers/expression.rb +7 -0
- data/lib/bel_parser/parsers/expression/comment.rb +239 -0
- data/lib/bel_parser/parsers/expression/comment.rl +97 -0
- data/lib/bel_parser/parsers/expression/parameter.rb +1506 -0
- data/lib/bel_parser/parsers/expression/parameter.rl +97 -0
- data/lib/bel_parser/parsers/expression/relationship.rb +254 -0
- data/lib/bel_parser/parsers/expression/relationship.rl +98 -0
- data/lib/bel_parser/parsers/expression/statement_nested.rb +17802 -0
- data/lib/bel_parser/parsers/expression/statement_nested.rl +141 -0
- data/lib/bel_parser/parsers/expression/statement_observed_term.rb +7291 -0
- data/lib/bel_parser/parsers/expression/statement_observed_term.rl +92 -0
- data/lib/bel_parser/parsers/expression/statement_simple.rb +10475 -0
- data/lib/bel_parser/parsers/expression/statement_simple.rl +112 -0
- data/lib/bel_parser/parsers/expression/term.rb +3989 -0
- data/lib/bel_parser/parsers/expression/term.rl +157 -0
- data/lib/bel_parser/parsers/line_parser.rb +92 -0
- data/lib/bel_parser/parsers/mixin/buffer.rb +10 -0
- data/lib/bel_parser/parsers/nonblocking_io_wrapper.rb +50 -0
- data/lib/bel_parser/script/parser.rb +49 -0
- data/lib/bel_parser/vendor/ast.rb +17 -0
- data/lib/bel_parser/vendor/ast/node.rb +254 -0
- data/lib/bel_parser/vendor/ast/processor.rb +12 -0
- data/lib/bel_parser/vendor/ast/processor/mixin.rb +282 -0
- data/lib/bel_parser/vendor/ast/sexp.rb +30 -0
- metadata +226 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require_relative '../ast_filter'
|
|
2
|
+
require_relative '../ast_generator'
|
|
3
|
+
require_relative '../parsers/common'
|
|
4
|
+
require_relative '../parsers/expression'
|
|
5
|
+
require_relative '../mixin/line_mapping'
|
|
6
|
+
|
|
7
|
+
module BELParser
|
|
8
|
+
module Expression
|
|
9
|
+
# Parser for BEL Expression.
|
|
10
|
+
class Parser
|
|
11
|
+
include BELParser::Parsers::Common
|
|
12
|
+
include BELParser::Parsers::Expression
|
|
13
|
+
|
|
14
|
+
FILTER = BELParser::ASTFilter.new(
|
|
15
|
+
:statement_simple,
|
|
16
|
+
:observed_term,
|
|
17
|
+
:nested_statement
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
def each(io)
|
|
21
|
+
if block_given?
|
|
22
|
+
filtered_ast = FILTER.each(BELParser::ASTGenerator.new.each(io))
|
|
23
|
+
filtered_ast.each do |results|
|
|
24
|
+
yield results
|
|
25
|
+
end
|
|
26
|
+
else
|
|
27
|
+
enum_for(:each, io)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
if __FILE__ == $PROGRAM_NAME
|
|
35
|
+
BELParser::Expression::Parser.new.each($stdin) do |line_result|
|
|
36
|
+
line_number, line, ast_results = line_result
|
|
37
|
+
puts "#{line_number}: #{line}"
|
|
38
|
+
ast_results.each do |ast|
|
|
39
|
+
puts ast.to_s(1)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require_relative '../ast_filter'
|
|
2
|
+
require_relative '../ast_generator'
|
|
3
|
+
require_relative '../parsers/expression'
|
|
4
|
+
require_relative '../language/version2'
|
|
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::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
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
require_relative 'language/function'
|
|
2
|
+
require_relative 'language/quoting'
|
|
3
|
+
require_relative 'language/semantic_ast'
|
|
4
|
+
require_relative 'language/signature'
|
|
5
|
+
require_relative 'language/specification'
|
|
6
|
+
|
|
7
|
+
# BEL language/version1 and language/version2 files are loaded when needed.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module BELParser
|
|
2
|
+
module Language
|
|
3
|
+
# Function allows you to describe the type of BEL Term.
|
|
4
|
+
#
|
|
5
|
+
# BEL Terms are composed of BEL Functions and entity definitions
|
|
6
|
+
# referenced using BEL Namespace identifiers. Each BEL Term represents
|
|
7
|
+
# either an abundance of a biological entity, the abundance of human AKT1
|
|
8
|
+
# for example, or a biological process such as cardiomyopathy.
|
|
9
|
+
module Function
|
|
10
|
+
def short
|
|
11
|
+
raise NotImplementedError, "#{__method__} is not implemented."
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def long
|
|
15
|
+
raise NotImplementedError, "#{__method__} is not implemented."
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def return_type
|
|
19
|
+
raise NotImplementedError, "#{__method__} is not implemented."
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def description
|
|
23
|
+
raise NotImplementedError, "#{__method__} is not implemented."
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def signatures
|
|
27
|
+
raise NotImplementedError, "#{__method__} is not implemented."
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def ===(other)
|
|
31
|
+
return false if other.nil?
|
|
32
|
+
short == other || long == other
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def to_sym(form = :short)
|
|
36
|
+
value = _form_value(form)
|
|
37
|
+
return nil unless value
|
|
38
|
+
value.to_s
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def to_s(form = :short)
|
|
42
|
+
value = _form_value(form)
|
|
43
|
+
return nil unless value
|
|
44
|
+
value.to_s
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def _form_value(form = :short)
|
|
50
|
+
case form
|
|
51
|
+
when :short
|
|
52
|
+
short
|
|
53
|
+
when :long
|
|
54
|
+
long
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
module BELParser
|
|
2
|
+
|
|
3
|
+
# The Quoting module implements quoting rules consistent with BEL
|
|
4
|
+
# and BEL Script. Double quotes are used to group a string together
|
|
5
|
+
# which may contain whitespace or special characters.
|
|
6
|
+
#
|
|
7
|
+
# A value can either be an identifier or a string value. An
|
|
8
|
+
# identifier can only include the characters +[0-9A-Za-z_]+. A string
|
|
9
|
+
# value is necessary when at least one of +[^0-9A-Za-z_]+ exists in
|
|
10
|
+
# the value.
|
|
11
|
+
#
|
|
12
|
+
# Uses:
|
|
13
|
+
#
|
|
14
|
+
# BEL: The BEL parameters must be an identifier or string value.
|
|
15
|
+
#
|
|
16
|
+
# BEL Script: BEL parameters, document property values, and annotation
|
|
17
|
+
# values must be an identifier or string value.
|
|
18
|
+
module Quoting
|
|
19
|
+
|
|
20
|
+
# Declares BEL Script keywords that cause problems with the OpenBEL
|
|
21
|
+
# Framework parser.
|
|
22
|
+
Keywords = %w(SET DEFINE a g p r m)
|
|
23
|
+
|
|
24
|
+
# Regular expression that matches one of {Quoting::Keywords}.
|
|
25
|
+
KeywordMatcher = Regexp.compile(/^(#{Keywords.join('|')})$/)
|
|
26
|
+
|
|
27
|
+
# Regular expression that matches on any non-word character.
|
|
28
|
+
NonWordMatcher = Regexp.compile(/[^0-9a-zA-Z_]/)
|
|
29
|
+
|
|
30
|
+
# Regular expression that matches a value surrounded by unescaped
|
|
31
|
+
# double quotes.
|
|
32
|
+
StrictQuotedMatcher = Regexp.compile(/\A".*?(?<!\\)"\Z/m)
|
|
33
|
+
|
|
34
|
+
# Regular expression that matches a value surrounded by double quotes
|
|
35
|
+
# that may be escaped.
|
|
36
|
+
LenientQuotedMatcher = Regexp.compile(/\A".*?"\Z/m)
|
|
37
|
+
|
|
38
|
+
# Regular expression that matches double quotes that are not escaped.
|
|
39
|
+
QuoteNotEscapedMatcher = Regexp.compile(/(?<!\\)"/m)
|
|
40
|
+
|
|
41
|
+
# Returns +value+ surrounded by double quotes. This method is idempotent
|
|
42
|
+
# so +value+ will only be quoted once regardless of how may times the
|
|
43
|
+
# method is called on it.
|
|
44
|
+
#
|
|
45
|
+
# @example Quoting a BEL parameter.
|
|
46
|
+
# quote("apoptotic process")
|
|
47
|
+
# # => "\"apoptotic process\""
|
|
48
|
+
# @example Escaping quotes within a value.
|
|
49
|
+
# quote("vesicle fusion with \"Golgi apparatus\"")
|
|
50
|
+
# # => "\"vesicle fusion with \\\"Golgi apparatus\\\"\""
|
|
51
|
+
#
|
|
52
|
+
# @parameter [#to_s] value a value to be quoted
|
|
53
|
+
# @return [String] value surrounded by double quotes
|
|
54
|
+
def quote(value)
|
|
55
|
+
string = value.to_s
|
|
56
|
+
unquoted = unquote(string)
|
|
57
|
+
escaped = unquoted.gsub(QuoteNotEscapedMatcher, "\\\"")
|
|
58
|
+
%Q{"#{escaped}"}
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Returns +value+ with surrounded quotes removed.
|
|
62
|
+
#
|
|
63
|
+
# @example Unquoting a BEL parameter.
|
|
64
|
+
# unquote("\"apoptotic process\"")
|
|
65
|
+
# # => "apoptotic process"
|
|
66
|
+
# @example Escaped quotes are preserved.
|
|
67
|
+
# unquote("\"vesicle fusion with \"Golgi apparatus\"\"")
|
|
68
|
+
#
|
|
69
|
+
# @parameter [#to_s] value a value to be unquoted
|
|
70
|
+
# @return [String] value with surrounding double quotes removed
|
|
71
|
+
def unquote(value)
|
|
72
|
+
string = value.to_s
|
|
73
|
+
if string =~ StrictQuotedMatcher
|
|
74
|
+
string[1...-1]
|
|
75
|
+
else
|
|
76
|
+
string
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Returns +value+ with quoting applied only if necessary. A +value+
|
|
81
|
+
# consisting of only word character (e.g. [0-9A-Za-z_]) does not need
|
|
82
|
+
# quoting. A +value+ consisting of at least one non-word character
|
|
83
|
+
# (e.g. [^0-9A-Za-z_]) will requiring quoting.
|
|
84
|
+
#
|
|
85
|
+
# @example Quotes added when value includes spaces.
|
|
86
|
+
# quote_if_needed("apoptotic process")
|
|
87
|
+
# # => "\"apoptotic process\""
|
|
88
|
+
# @example Quotes added when value includes double quote.
|
|
89
|
+
# quote_if_needed("vesicle fusion with \"Golgi apparatus\"")
|
|
90
|
+
# # => "\"vesicle fusion with \\\"Golgi apparatus\\\"\""
|
|
91
|
+
# @example No quotes necessary for identifier.
|
|
92
|
+
# quote_if_needed("AKT1_HUMAN")
|
|
93
|
+
# # => "AKT1_HUMAN"
|
|
94
|
+
#
|
|
95
|
+
# @parameter [#to_s] value that may be quoted
|
|
96
|
+
# @return [String] original value or quoted value
|
|
97
|
+
def quote_if_needed(value)
|
|
98
|
+
if string_value?(value)
|
|
99
|
+
quote(value)
|
|
100
|
+
else
|
|
101
|
+
value.to_s
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Returns whether the +value+ is surrounded by double quotes.
|
|
106
|
+
#
|
|
107
|
+
# @example Returns +true+ when value is quoted.
|
|
108
|
+
# quoted?("\"vesicle fusion with \"Golgi apparatus\"")
|
|
109
|
+
# # => true
|
|
110
|
+
# @example Returns +false+ when value is not quoted.
|
|
111
|
+
# quoted?("apoptotic process")
|
|
112
|
+
# # => false
|
|
113
|
+
#
|
|
114
|
+
# @parameter [#to_s] value to test
|
|
115
|
+
# @return [Boolean] +true+ if +value+ is quoted, +false+ if
|
|
116
|
+
# +value+ is not quoted
|
|
117
|
+
def quoted?(value)
|
|
118
|
+
string = value.to_s
|
|
119
|
+
(string =~ LenientQuotedMatcher) != nil
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Returns whether the +value+ is not surrounded by double quotes.
|
|
123
|
+
#
|
|
124
|
+
# @example Returns +true+ when value is not quoted.
|
|
125
|
+
# unquoted?("apoptotic process")
|
|
126
|
+
# # => true
|
|
127
|
+
# @example Returns +false+ when value is quoted.
|
|
128
|
+
# unquoted?("\"vesicle fusion with \"Golgi apparatus\"")
|
|
129
|
+
# # => false
|
|
130
|
+
#
|
|
131
|
+
# @parameter [#to_s] value to test
|
|
132
|
+
# @return [Boolean] +true+ if +value+ is not quoted, +false+ if
|
|
133
|
+
# +value+ is quoted
|
|
134
|
+
def unquoted?(value)
|
|
135
|
+
!quoted?(value)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Returns whether the +value+ represents an identifier. An
|
|
139
|
+
# identifier consists of only word characters (e.g. [0-9A-Za-z_]).
|
|
140
|
+
#
|
|
141
|
+
# @example Returns +true+ when representing an identifier.
|
|
142
|
+
# identifier_value?("AKT1_HUMAN")
|
|
143
|
+
# # => true
|
|
144
|
+
# @example Returns +false+ when not representing an identifier.
|
|
145
|
+
# identifier_value?("apoptotic process")
|
|
146
|
+
# # => false
|
|
147
|
+
#
|
|
148
|
+
# @parameter [#to_s] value to test
|
|
149
|
+
# @return [Boolean] +true+ if +value+ is an identifier,
|
|
150
|
+
# +false+ if +value+ is not an identifier
|
|
151
|
+
def identifier_value?(value)
|
|
152
|
+
string = value.to_s
|
|
153
|
+
[NonWordMatcher, KeywordMatcher].none? { |matcher|
|
|
154
|
+
matcher.match string
|
|
155
|
+
}
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Returns whether the +value+ represents a string value. A string
|
|
159
|
+
# value consists of at least one non-word character
|
|
160
|
+
# (e.g. [^0-9A-Za-z_]).
|
|
161
|
+
#
|
|
162
|
+
# @example Returns +true+ when representing a string value.
|
|
163
|
+
# string_value?("apoptotic process")
|
|
164
|
+
# # => true
|
|
165
|
+
# @example Returns +false+ when not representing a string value.
|
|
166
|
+
# string_value?("AKT1_HUMAN")
|
|
167
|
+
# # => false
|
|
168
|
+
#
|
|
169
|
+
# @parameter [#to_s] value to test
|
|
170
|
+
# @return [Boolean] +true+ if +value+ is a string value,
|
|
171
|
+
# +false+ if +value+ is not a string value
|
|
172
|
+
def string_value?(value)
|
|
173
|
+
string = value.to_s
|
|
174
|
+
[NonWordMatcher, KeywordMatcher].any? { |matcher|
|
|
175
|
+
matcher.match string
|
|
176
|
+
}
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
## Deprecated, remove in [0.6.0].
|
|
180
|
+
|
|
181
|
+
# @deprecated Use {#quote_if_needed} instead. Will be removed in a
|
|
182
|
+
# future release.
|
|
183
|
+
def ensure_quotes identifier
|
|
184
|
+
warn <<-DOC.gsub(/^\s+/, '')
|
|
185
|
+
Deprecation Warning
|
|
186
|
+
-------------------
|
|
187
|
+
The BEL::Quoting::ensure_quotes method is deprecated and
|
|
188
|
+
will be removed in a future relase.
|
|
189
|
+
Call module method BEL::Quoting.quote_if_needed instead.
|
|
190
|
+
DOC
|
|
191
|
+
quote_if_needed(identifier)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# @deprecated Use {#unquote} instead. Will be removed in a
|
|
195
|
+
# future release.
|
|
196
|
+
def remove_quotes identifier
|
|
197
|
+
warn <<-DOC.gsub(/^\s+/, '')
|
|
198
|
+
Deprecation Warning
|
|
199
|
+
-------------------
|
|
200
|
+
The BEL::Quoting::remove_quotes method is deprecated and
|
|
201
|
+
will be removed in a future relase.
|
|
202
|
+
Call module method BEL::Quoting.unquote instead.
|
|
203
|
+
DOC
|
|
204
|
+
unquote(identifier)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# @deprecated Use {#quote} instead. Will be removed in a
|
|
208
|
+
# future release.
|
|
209
|
+
def always_quote identifier
|
|
210
|
+
warn <<-DOC.gsub(/^\s+/, '')
|
|
211
|
+
Deprecation Warning
|
|
212
|
+
-------------------
|
|
213
|
+
The BEL::Quoting::always_quote method is deprecated and
|
|
214
|
+
will be removed in a future relase.
|
|
215
|
+
Call module method BEL::Quoting.quote instead.
|
|
216
|
+
DOC
|
|
217
|
+
quote(identifier)
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# @deprecated Use {#quoted?} or {#unquoted?} instead. Will be removed
|
|
221
|
+
# in a future release.
|
|
222
|
+
def quotes_required? identifier
|
|
223
|
+
warn <<-DOC.gsub(/^\s+/, '')
|
|
224
|
+
Deprecation Warning
|
|
225
|
+
-------------------
|
|
226
|
+
The BEL::Quoting::quotes_required? method is deprecated and
|
|
227
|
+
will be removed in a future relase.
|
|
228
|
+
You can use BEL::Quoting.quoted? and BEL::Quoting.unquoted?
|
|
229
|
+
going forward.
|
|
230
|
+
DOC
|
|
231
|
+
[NonWordMatcher, KeywordMatcher].any? { |m|
|
|
232
|
+
m.match identifier.to_s
|
|
233
|
+
}
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
end
|
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
require_relative 'quoting'
|
|
2
|
+
require_relative '../parsers/ast/node'
|
|
3
|
+
|
|
4
|
+
module BELParser
|
|
5
|
+
module Language
|
|
6
|
+
# Semantics capture BEL version-independent semantics for terms and
|
|
7
|
+
# statements.
|
|
8
|
+
module Semantics
|
|
9
|
+
# rubocop:disable Metrics/MethodLength
|
|
10
|
+
# rubocop:disable Metrics/AbcSize
|
|
11
|
+
def self.match(input_ast, semantic_ast, spec, match_results = [])
|
|
12
|
+
res = semantic_ast.match(input_ast, spec)
|
|
13
|
+
match_results.concat(res)
|
|
14
|
+
if res.flatten.all?(&:success?) && !semantic_ast.terminal?
|
|
15
|
+
return match_results if semantic_ast.children.empty?
|
|
16
|
+
|
|
17
|
+
var_test = semantic_ast.children.any? { |x| x.is_a?(SemanticVariadicArguments) }
|
|
18
|
+
if var_test
|
|
19
|
+
test_pairs = input_ast.children.zip(semantic_ast.children).select do |pair|
|
|
20
|
+
!pair.include?(nil)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
test_pairs.each do |(input_child, semantic_child)|
|
|
24
|
+
if semantic_child.is_a?(SemanticVariadicArguments)
|
|
25
|
+
input_children = input_ast.children
|
|
26
|
+
input_arguments = input_children[input_children.index(input_child)..-1]
|
|
27
|
+
argument_pattern = semantic_child.children.first
|
|
28
|
+
input_arguments.each do |argument_child|
|
|
29
|
+
res = semantic_child.match(argument_child, spec)
|
|
30
|
+
match_results << res
|
|
31
|
+
if res.all?(&:success?)
|
|
32
|
+
param_or_term = argument_child.children.first
|
|
33
|
+
match(param_or_term, argument_pattern, spec, match_results)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
else
|
|
37
|
+
match(input_child, semantic_child, spec, match_results)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
else
|
|
41
|
+
semantic_ast
|
|
42
|
+
.children
|
|
43
|
+
.zip(input_ast.children)
|
|
44
|
+
.each do |semantic_child, input_child|
|
|
45
|
+
match(input_child, semantic_child, spec, match_results)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
match_results.flatten
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# MatchResult holds the results of an input AST to semantic AST match.
|
|
53
|
+
class MatchResult
|
|
54
|
+
attr_reader :input_node, :semantic_node
|
|
55
|
+
|
|
56
|
+
def initialize(success, input_node, semantic_node)
|
|
57
|
+
@success = success
|
|
58
|
+
@input_node = input_node
|
|
59
|
+
@semantic_node = semantic_node
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def success?
|
|
63
|
+
@success
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def failure?
|
|
67
|
+
!@success
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def to_s
|
|
71
|
+
msg
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Builder contains methods to build semantic AST nodes.
|
|
76
|
+
# A convenient {Builder.build} method allows you to use these
|
|
77
|
+
# methods within a block scope.
|
|
78
|
+
#
|
|
79
|
+
# see Builder.build
|
|
80
|
+
module Builder
|
|
81
|
+
def self.build(&block)
|
|
82
|
+
raise ArgumentError, 'expecting block' unless block_given?
|
|
83
|
+
|
|
84
|
+
builder = _builder_class.new
|
|
85
|
+
builder.instance_eval(&block)
|
|
86
|
+
builder.result
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def self._builder_class
|
|
90
|
+
Class.new do
|
|
91
|
+
include Builder
|
|
92
|
+
|
|
93
|
+
attr_reader :result
|
|
94
|
+
|
|
95
|
+
def term(function, *arguments, **properties)
|
|
96
|
+
@result = super
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
private_class_method :_builder_class
|
|
101
|
+
|
|
102
|
+
def term(function, *arguments, **properties)
|
|
103
|
+
SemanticTerm.new([function, *arguments], **properties)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def function(identifier, **properties)
|
|
107
|
+
SemanticFunction.new([identifier], **properties)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def argument(param_or_term, **properties)
|
|
111
|
+
cls = param_or_term.class
|
|
112
|
+
if cls != SemanticParameter && cls != SemanticTerm
|
|
113
|
+
raise ArgumentError, 'expected SemanticParameter or SemanticTerm'
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
SemanticArgument.new([param_or_term], **properties)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def parameter(prefix, value, **properties)
|
|
120
|
+
SemanticParameter.new([prefix, value], **properties)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def identifier(*value_patterns, **properties)
|
|
124
|
+
SemanticIdentifier.new(value_patterns, **properties)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def prefix(has_namespace, **properties)
|
|
128
|
+
SemanticPrefix.new([has_namespace], **properties)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def value(value_type, **properties)
|
|
132
|
+
SemanticValue.new([value_type], **properties)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def value_type(*value_patterns, **properties)
|
|
136
|
+
SemanticValueType.new(value_patterns, **properties)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def any(**properties)
|
|
140
|
+
SemanticAny.new(**properties)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# rubocop:disable Style/PredicateName
|
|
144
|
+
def is_nil(**properties)
|
|
145
|
+
SemanticIsNil.new(**properties)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def has_namespace(**properties)
|
|
149
|
+
SemanticHasNamespace.new(**properties)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def has_encoding(**properties)
|
|
153
|
+
SemanticHasEncoding.new(**properties)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def function_of(*functions, **properties)
|
|
157
|
+
SemanticFunctionOf.new(functions, **properties)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def return_type_of(*return_types, **properties)
|
|
161
|
+
SemanticReturnTypeOf.new(return_types, **properties)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def namespace_of(*namespaces, **properties)
|
|
165
|
+
SemanticNamespaceOf.new(namespaces, **properties)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def encoding_of(*encoding_types, **properties)
|
|
169
|
+
SemanticEncodingOf.new(encoding_types, **properties)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def covalent_modification_of(*covalent_mod_types, **properties)
|
|
173
|
+
SemanticCovalentModificationOf.new(covalent_mod_types, **properties)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def amino_acid_of(*amino_acids, **properties)
|
|
177
|
+
SemanticAminoAcidOf.new(amino_acids, **properties)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def is_amino_acid_range_pattern(**properties)
|
|
181
|
+
SemanticIsAminoAcidRange.new(**properties)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def variadic_arguments(*params_or_terms, **properties)
|
|
185
|
+
SemanticVariadicArguments.new(params_or_terms, **properties)
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# SemanticASTNode represents a node in the semantic tree structure.
|
|
190
|
+
class SemanticASTNode < AST::Node
|
|
191
|
+
def initialize(type, children = [], **properties)
|
|
192
|
+
super(type, children, properties)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def terminal?
|
|
196
|
+
false
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
protected
|
|
200
|
+
|
|
201
|
+
def updated(_ = nil, children = nil, properties = nil)
|
|
202
|
+
new_children = children || @children
|
|
203
|
+
new_properties = properties || {}
|
|
204
|
+
|
|
205
|
+
if @children == new_children && properties.nil?
|
|
206
|
+
self
|
|
207
|
+
else
|
|
208
|
+
# Maybe change call?
|
|
209
|
+
original_dup.send :initialize, new_children, new_properties
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def success(node)
|
|
214
|
+
[MatchResult.new(true, node, self)]
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def failure(node)
|
|
218
|
+
[MatchResult.new(false, node, self)]
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# AST node for Term is a semantic AST.
|
|
223
|
+
class SemanticTerm < SemanticASTNode
|
|
224
|
+
def initialize(children = [], **properties)
|
|
225
|
+
super(:term, children, properties)
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def match(parse_node, _)
|
|
229
|
+
type == parse_node.type ? success(parse_node) : failure(parse_node)
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# AST node for Statement is a semantic AST.
|
|
234
|
+
class SemanticStatement < SemanticASTNode
|
|
235
|
+
def initialize(children = [], **properties)
|
|
236
|
+
super(:statement, children, properties)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def match(parse_node, _)
|
|
240
|
+
type == parse_node.type ? success(parse_node) : failure(parse_node)
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
# AST node for Parameter is a semantic AST.
|
|
245
|
+
class SemanticParameter < SemanticASTNode
|
|
246
|
+
def initialize(children = [], **properties)
|
|
247
|
+
super(:parameter, children, properties)
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def match(parse_node, _)
|
|
251
|
+
type == parse_node.type ? success(parse_node) : failure(parse_node)
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
# AST node for Function is a semantic AST.
|
|
256
|
+
class SemanticFunction < SemanticASTNode
|
|
257
|
+
def initialize(children = [], **properties)
|
|
258
|
+
super(:function, children, properties)
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def match(parse_node, _)
|
|
262
|
+
type == parse_node.type ? success(parse_node) : failure(parse_node)
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
# AST node for Argument is a semantic AST.
|
|
267
|
+
class SemanticArgument < SemanticASTNode
|
|
268
|
+
def initialize(children = [], **properties)
|
|
269
|
+
super(:argument, children, properties)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def match(parse_node, _)
|
|
273
|
+
return failure(nil) if parse_node.nil?
|
|
274
|
+
type == parse_node.type ? success(parse_node) : failure(parse_node)
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# AST node for VariadicArguments is a semantic AST.
|
|
279
|
+
class SemanticVariadicArguments < SemanticASTNode
|
|
280
|
+
def initialize(children = [], **properties)
|
|
281
|
+
super(:variadic_arguments, children, properties)
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def match(parse_node, _)
|
|
285
|
+
if parse_node.type == BELParser::Parsers::AST::Argument.ast_type
|
|
286
|
+
success(parse_node)
|
|
287
|
+
else
|
|
288
|
+
failure(parse_node)
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
# AST node for Prefix is a semantic AST.
|
|
294
|
+
class SemanticPrefix < SemanticASTNode
|
|
295
|
+
def initialize(children = [], **properties)
|
|
296
|
+
super(:prefix, children, properties)
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def match(parse_node, _)
|
|
300
|
+
type == parse_node.type ? success(parse_node) : failure(parse_node)
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
# AST node for Value is a semantic AST.
|
|
305
|
+
class SemanticValue < SemanticASTNode
|
|
306
|
+
def initialize(children = [], **properties)
|
|
307
|
+
super(:value, children, properties)
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def match(parse_node, _)
|
|
311
|
+
type == parse_node.type ? success(parse_node) : failure(parse_node)
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
# AST node for Nil is a semantic AST.
|
|
316
|
+
class SemanticIsNil < SemanticASTNode
|
|
317
|
+
def initialize(**properties)
|
|
318
|
+
super(:is_nil, [], properties)
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
def terminal?
|
|
322
|
+
true
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
def match(parse_node, _)
|
|
326
|
+
parse_node.nil? ? success(parse_node) : failure(nil)
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
# AST node for Identifier is a semantic AST.
|
|
331
|
+
class SemanticIdentifier < SemanticASTNode
|
|
332
|
+
def initialize(children = [], **properties)
|
|
333
|
+
super(:identifier, children, properties)
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
def terminal?
|
|
337
|
+
true
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
def value_patterns
|
|
341
|
+
children
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
def match(identifier, spec)
|
|
345
|
+
return failure(nil) if identifier.nil?
|
|
346
|
+
return failure(identifier) if type != identifier.type
|
|
347
|
+
|
|
348
|
+
value_results = value_patterns.map do |pattern|
|
|
349
|
+
pattern.match(identifier, spec)
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
failure_result = value_results.flatten.find(&:failure?)
|
|
353
|
+
|
|
354
|
+
if failure_result
|
|
355
|
+
[failure(identifier), failure_result]
|
|
356
|
+
else
|
|
357
|
+
value_results.unshift(success(identifier))
|
|
358
|
+
end
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
# AST node for Any is a semantic AST.
|
|
363
|
+
class SemanticAny < SemanticASTNode
|
|
364
|
+
def initialize(**properties)
|
|
365
|
+
super(:any, [], properties)
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
def match(parse_node, _)
|
|
369
|
+
success(parse_node)
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
# AST node for HasNamespace is a semantic AST.
|
|
374
|
+
class SemanticHasNamespace < SemanticASTNode
|
|
375
|
+
def initialize(**properties)
|
|
376
|
+
super(:has_namespace, [], properties)
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
def match(identifier, _)
|
|
380
|
+
# FIXME: Implement :namespace property assignment to AST.
|
|
381
|
+
return success(identifier)
|
|
382
|
+
if identifier.respond_to?(:namespace)
|
|
383
|
+
success(identifier)
|
|
384
|
+
else
|
|
385
|
+
failure(identifier)
|
|
386
|
+
end
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
# AST node for NamespaceOf is a semantic AST.
|
|
391
|
+
class SemanticNamespaceOf < SemanticASTNode
|
|
392
|
+
def initialize(namespaces, **properties)
|
|
393
|
+
super(:namespace_of, namespaces, properties)
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
def match(identifier, _)
|
|
397
|
+
# FIXME: Implement :namespace property assignment to AST.
|
|
398
|
+
return success(identifier)
|
|
399
|
+
return failure(identifier) unless identifier.respond_to?(:namespace)
|
|
400
|
+
input_namespace = identifier.namespace
|
|
401
|
+
return failure(identifier) if input_namespace.nil?
|
|
402
|
+
|
|
403
|
+
namespace_set = children
|
|
404
|
+
if namespace_set.any? { |i| i == :* || i == input_namespace }
|
|
405
|
+
success(identifier)
|
|
406
|
+
else
|
|
407
|
+
failure(identifier)
|
|
408
|
+
end
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
# AST node for HasEncoding is a semantic AST.
|
|
413
|
+
class SemanticHasEncoding < SemanticASTNode
|
|
414
|
+
def initialize(**properties)
|
|
415
|
+
super(:has_encoding, [], properties)
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
def match(value_type, _)
|
|
419
|
+
# FIXME: Implement :encoding property assignment to AST.
|
|
420
|
+
return success(value_type)
|
|
421
|
+
if value_type.respond_to?(:encoding)
|
|
422
|
+
success(value_type)
|
|
423
|
+
else
|
|
424
|
+
failure(value_type)
|
|
425
|
+
end
|
|
426
|
+
end
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
# AST node for EncodingOf is a semantic AST.
|
|
430
|
+
class SemanticEncodingOf < SemanticASTNode
|
|
431
|
+
def initialize(encodings, **properties)
|
|
432
|
+
super(:encoding_of, encodings, properties)
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
def match(value_type, _)
|
|
436
|
+
# FIXME: Implement :encoding property assignment to AST.
|
|
437
|
+
return success(value_type)
|
|
438
|
+
encoding_set = children
|
|
439
|
+
return success(value_type) if encoding_set.include?(:*)
|
|
440
|
+
|
|
441
|
+
return failure(value_type) unless value_type.respond_to?(:encoding)
|
|
442
|
+
|
|
443
|
+
input_encoding = value_type.encoding
|
|
444
|
+
return failure(value_type) if input_encoding.nil?
|
|
445
|
+
|
|
446
|
+
if encoding_set.include?(input_encoding)
|
|
447
|
+
success(value_type)
|
|
448
|
+
else
|
|
449
|
+
failure(value_type)
|
|
450
|
+
end
|
|
451
|
+
end
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
# AST node for FunctionOf is a semantic AST.
|
|
455
|
+
class SemanticFunctionOf < SemanticASTNode
|
|
456
|
+
def initialize(functions, **properties)
|
|
457
|
+
super(:function_of, functions, properties)
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
def functions
|
|
461
|
+
children
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
def match(identifier, spec)
|
|
465
|
+
return success(identifier) if functions.include?(:*)
|
|
466
|
+
|
|
467
|
+
function = spec.function(identifier.children[0].to_sym)
|
|
468
|
+
if functions.include?(function)
|
|
469
|
+
success(identifier)
|
|
470
|
+
else
|
|
471
|
+
failure(identifier)
|
|
472
|
+
end
|
|
473
|
+
end
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
# AST node for ReturnTypeOf is a semantic AST.
|
|
477
|
+
class SemanticReturnTypeOf < SemanticASTNode
|
|
478
|
+
def initialize(return_types, **properties)
|
|
479
|
+
super(:return_type_of, return_types, properties)
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
def return_types
|
|
483
|
+
children
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
def match(identifier, spec)
|
|
487
|
+
return success(identifier) if return_types.include?(:*)
|
|
488
|
+
|
|
489
|
+
fx_return = spec.function(identifier.children[0].to_sym).return_type
|
|
490
|
+
if return_types.any? { |rt| fx_return <= rt }
|
|
491
|
+
success(identifier)
|
|
492
|
+
else
|
|
493
|
+
failure(identifier)
|
|
494
|
+
end
|
|
495
|
+
end
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
# AST node for ValueType is a semantic AST.
|
|
499
|
+
class SemanticValueType < SemanticASTNode
|
|
500
|
+
TYPES = [
|
|
501
|
+
BELParser::Parsers::AST::Identifier.ast_type,
|
|
502
|
+
BELParser::Parsers::AST::String.ast_type
|
|
503
|
+
].freeze
|
|
504
|
+
|
|
505
|
+
def initialize(children = [], **properties)
|
|
506
|
+
super(:value_type, children, properties)
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
def terminal?
|
|
510
|
+
true
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
def value_patterns
|
|
514
|
+
children
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
def match(value_type, spec)
|
|
518
|
+
return failure(value_type) unless TYPES.include?(value_type.type)
|
|
519
|
+
|
|
520
|
+
value_results = value_patterns.map do |pattern|
|
|
521
|
+
pattern.match(value_type, spec)
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
failure_result = value_results.flatten.find(&:failure?)
|
|
525
|
+
|
|
526
|
+
if failure_result
|
|
527
|
+
[failure(value_type), failure_result]
|
|
528
|
+
else
|
|
529
|
+
value_results.unshift(success(value_type))
|
|
530
|
+
end
|
|
531
|
+
end
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
# AST node for CovalentModificationOf is a semantic AST.
|
|
535
|
+
class SemanticCovalentModificationOf < SemanticASTNode
|
|
536
|
+
def initialize(covalent_mod_types, **properties)
|
|
537
|
+
properties[:hashed] = Hash[covalent_mod_types.map { |t| [t, true] }]
|
|
538
|
+
super(:covalent_modification_of, covalent_mod_types, properties)
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
def covalent_mod_types
|
|
542
|
+
children
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
def match(value_type, _)
|
|
546
|
+
string_literal_sym = value_type.children[0].to_sym
|
|
547
|
+
return success(value_type) if @hashed[:*]
|
|
548
|
+
|
|
549
|
+
if @hashed.key?(string_literal_sym)
|
|
550
|
+
success(value_type)
|
|
551
|
+
else
|
|
552
|
+
failure(value_type)
|
|
553
|
+
end
|
|
554
|
+
end
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
# AST node for AminoAcidOf is a semantic AST.
|
|
558
|
+
class SemanticAminoAcidOf < SemanticASTNode
|
|
559
|
+
def initialize(amino_acids, **properties)
|
|
560
|
+
properties[:hashed] = Hash[amino_acids.map { |t| [t, true] }]
|
|
561
|
+
super(:amino_acid_of, amino_acids, properties)
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
def amino_acids
|
|
565
|
+
children
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
def match(value_type, _)
|
|
569
|
+
string_literal_sym = value_type.children[0].to_sym
|
|
570
|
+
return success(value_type) if @hashed[:*]
|
|
571
|
+
|
|
572
|
+
if @hashed.key?(string_literal_sym)
|
|
573
|
+
success(value_type)
|
|
574
|
+
else
|
|
575
|
+
failure(value_type)
|
|
576
|
+
end
|
|
577
|
+
end
|
|
578
|
+
end
|
|
579
|
+
|
|
580
|
+
# AST node for IsAminoAcidRange is a semantic AST.
|
|
581
|
+
class SemanticIsAminoAcidRange < SemanticASTNode
|
|
582
|
+
START_STOP = /[1-9][0-9]*_[1-9][0-9]*/
|
|
583
|
+
UNDETERMINED = /[1?]_[?*]/
|
|
584
|
+
UNKNOWN_START_STOP = "?"
|
|
585
|
+
|
|
586
|
+
include BELParser::Quoting
|
|
587
|
+
|
|
588
|
+
def initialize(**properties)
|
|
589
|
+
super(:is_amino_acid_range, [], properties)
|
|
590
|
+
end
|
|
591
|
+
|
|
592
|
+
def match(value_type, _)
|
|
593
|
+
string_literal = unquote(value_type.children[0])
|
|
594
|
+
case string_literal
|
|
595
|
+
when START_STOP, UNDETERMINED, UNKNOWN_START_STOP
|
|
596
|
+
success(value_type)
|
|
597
|
+
else
|
|
598
|
+
failure(value_type)
|
|
599
|
+
end
|
|
600
|
+
end
|
|
601
|
+
end
|
|
602
|
+
end
|
|
603
|
+
end
|
|
604
|
+
end
|