Class: ActiveFacts::CQL::Compiler
- Defined in:
- lib/activefacts/cql/compiler.rb,
lib/activefacts/cql/compiler/fact.rb,
lib/activefacts/cql/compiler/query.rb,
lib/activefacts/cql/compiler/clause.rb,
lib/activefacts/cql/compiler/shared.rb,
lib/activefacts/cql/compiler/informal.rb,
lib/activefacts/cql/compiler/fact_type.rb,
lib/activefacts/cql/compiler/constraint.rb,
lib/activefacts/cql/compiler/expression.rb,
lib/activefacts/cql/compiler/value_type.rb,
lib/activefacts/cql/compiler/entity_type.rb,
lib/activefacts/cql/compiler/transform_rule.rb
Defined Under Namespace
Classes: Aggregate, Binding, Clause, ClauseMatchSideEffect, ClauseMatchSideEffects, Comparison, CompilationContext, CompoundMatching, Constraint, ContextNote, Definition, Enforcement, EntityType, ExpressionTermList, Fact, FactType, Import, InformalDefinition, Literal, LogicalAnd, LogicalOr, Negate, Negation, ObjectType, Operation, PresenceConstraint, Product, Quantifier, Query, Reciprocal, Reference, ReferenceMode, RingConstraint, SetComparisonConstraint, SetConstraint, SetEqualityConstraint, SetExclusionConstraint, SimpleMatching, SubsetConstraint, Sum, Ternary, TransformRule, Unit, ValueConstraint, ValueType, Vocabulary
Constant Summary collapse
- LANGUAGES =
{ 'en' => 'English', 'fr' => 'French', 'cn' => 'Mandarin' }
- EXTENSIONS =
['fiml', 'fidl', 'fiql', 'cql']
Instance Attribute Summary collapse
-
#vocabulary ⇒ Object
readonly
Returns the value of attribute vocabulary.
Class Method Summary collapse
Instance Method Summary collapse
- #compile(input) ⇒ Object
- #compile_definition(ast) ⇒ Object
- #compile_file(filepath) ⇒ Object
- #compile_import(file, import_role, aliases) ⇒ Object
-
#compile_import_file(filepath, import_role) ⇒ Object
redefine in subsclass for different behaviour.
- #compile_import_input(input, import_role) ⇒ Object
- #create_import_if_pending(new_topic) ⇒ Object
-
#detect_language ⇒ Object
Load the appropriate natural language module.
-
#import_filepath(old_filepath, file) ⇒ Object
redefine in subsclass for different behaviour.
- #include_language ⇒ Object
-
#initialize(filepath, options = {}) ⇒ Compiler
constructor
A new instance of Compiler.
-
#topic_flood ⇒ Object
Mark any new Concepts as belonging to this topic.
- #unit?(s) ⇒ Boolean
Methods inherited from Parser
Methods included from CQL
#_nt_alias_list, #_nt_alias_term, #_nt_constraint, #_nt_cql_file, #_nt_definition, #_nt_definition_body, #_nt_enforcement, #_nt_equality_constraint, #_nt_import_definition, #_nt_import_role, #_nt_informal_description, #_nt_informal_description_body, #_nt_informal_description_closer, #_nt_informal_description_subject, #_nt_presence_constraint, #_nt_schema_definition, #_nt_set_constraint, #_nt_subset_constraint, #_nt_transform_definition, #_nt_version_number, #_nt_version_number_string, #_nt_version_pattern, #_nt_version_pattern_string, #_nt_vocabulary_definition, #_nt_vocabulary_name, #root
Methods included from Context
#_nt_context_note, #_nt_context_type, #_nt_description, #_nt_who_says, #root
Methods included from TransformRules
#_nt_additive_op, #_nt_additive_texpr, #_nt_aggregate_op, #_nt_compound_matching, #_nt_equality_op, #_nt_equality_texpr, #_nt_logical_and_texpr, #_nt_logical_texpr, #_nt_multiplicative_op, #_nt_multiplicative_texpr, #_nt_primary_texpr, #_nt_relational_op, #_nt_relational_texpr, #_nt_simple_matching, #_nt_term_list, #_nt_transform_expr, #_nt_transform_matching, #_nt_transform_matchings, #_nt_transform_query, #_nt_transform_rule, #_nt_unary_op, #_nt_unary_texpr, #root
Methods included from FactTypes
#_nt_aggregate, #_nt_anonymous_fact_type, #_nt_certainty, #_nt_clauses, #_nt_clauses_list, #_nt_comparator, #_nt_comparison, #_nt_condition_contraction, #_nt_contracted_clauses, #_nt_contraction, #_nt_fact_type, #_nt_objectification_step, #_nt_phrase, #_nt_post_qualifier, #_nt_post_qualifiers, #_nt_qualified_clauses, #_nt_query, #_nt_query_clauses, #_nt_reading_contraction, #_nt_return, #_nt_returning_clause, #_nt_role, #_nt_role_name, #_nt_role_quantifier, #_nt_simple_role, #_nt_subscript, #root
Methods included from ValueTypes
#_nt_implicit_value_type_name, #_nt_in_units, #_nt_maybe_unit, #_nt_named_parameter, #_nt_non_unit, #_nt_ordered_parameter, #_nt_parameter, #_nt_parameter_literal, #_nt_parameter_name, #_nt_parameter_restriction, #_nt_range_list, #_nt_restricted_values, #_nt_type_parameter_list, #_nt_unit, #_nt_unit_coefficient, #_nt_unit_definition, #_nt_unit_name, #_nt_unit_offset, #_nt_units, #_nt_value_constraint, #_nt_value_type, #_nt_value_type_parameters, #root
Methods included from ObjectTypes
#_nt_basetype, #_nt_entity_clauses, #_nt_entity_type, #_nt_identification, #_nt_mapping_pragma, #_nt_mapping_pragmas, #_nt_object_type, #_nt_role_list, #_nt_subtype, #_nt_supertype_list, #_nt_term_or_unary, #_nt_unary_text, #root
Methods included from Terms
#_nt_derived_value_continuation, #_nt_entity_prefix, #_nt_global_term, #_nt_informal_description_subject_prescan, #_nt_informally_prescan, #_nt_lead_intervening, #_nt_new_adjective_term, #_nt_new_derived_value, #_nt_non_phrase, #_nt_non_term_def, #_nt_prescan, #_nt_prescan_aggregate, #_nt_prescan_rest, #_nt_term, #_nt_term_definition_name, #_nt_trail_intervening, #_nt_x, #root
Methods included from Expressions
#_nt_add_op, #_nt_derived_variable, #_nt_expression, #_nt_factor, #_nt_product, #_nt_sum, #root
Methods included from LexicalRules
#_nt_S, #_nt_alpha, #_nt_alphanumeric, #_nt_boolean_literal, #_nt_character_class, #_nt_character_classes, #_nt_comment_c_style, #_nt_comment_to_eol, #_nt_exponent, #_nt_fraction, #_nt_fractional_real, #_nt_hexnumber, #_nt_id, #_nt_literal, #_nt_mul_op, #_nt_number, #_nt_numeric_range, #_nt_octalnumber, #_nt_range, #_nt_real, #_nt_regular_expression, #_nt_regular_expression_alternate, #_nt_regular_expression_atom, #_nt_regular_expression_contents, #_nt_regular_expression_group, #_nt_regular_expression_group_extension, #_nt_regular_expression_multiplicity, #_nt_regular_expression_sequence, #_nt_s, #_nt_string, #_nt_string_char, #_nt_string_range, #_nt_url, #_nt_white, #root
Constructor Details
#initialize(filepath, options = {}) ⇒ Compiler
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/activefacts/cql/compiler.rb', line 31 def initialize filepath, = {} @filepath = filepath super() if @constellation = [:constellation] @vocabulary = @constellation.Vocabulary.values[0] @constellation.ValueType.values.each do |object_type| context.object_type(object_type.name, "value type") end @constellation.EntityType.values.each do |object_type| context.object_type(object_type.name, "entity type") end else @constellation = ActiveFacts::API::Constellation.new(ActiveFacts::Metamodel) end @constellation = [:constellation] || ActiveFacts::API::Constellation.new(ActiveFacts::Metamodel) @constellation.loggers << proc{|*k| trace :apilog, k.inspect} if trace(:apilog) @language = nil @pending_import_topic = nil @pending_import_role = '' @pending_import_file_name = '' trace :file, "Parsing '#{@filepath}'" end |
Instance Attribute Details
#vocabulary ⇒ Object (readonly)
Returns the value of attribute vocabulary.
29 30 31 |
# File 'lib/activefacts/cql/compiler.rb', line 29 def vocabulary @vocabulary end |
Class Method Details
.build_transform_target_refs(context, targ_term_list, transform_rule) ⇒ Object
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/activefacts/cql/compiler/transform_rule.rb', line 25 def self.build_transform_target_refs context, targ_term_list, transform_rule vocabulary_identifier = context.vocabulary. constellation = context.vocabulary.constellation targ_term_list.flatten! (0 ... targ_term_list.size).each do |idx| ref = targ_term_list[idx] if (target_ot = constellation.ObjectType[[vocabulary_identifier, ref.term]]).nil? raise "Target object '#{ref.term}' of transformation must be a valid object type" end constellation.TransformTargetRef( transform_rule, idx, :object_type => target_ot, :leading_adjective => ref.leading_adjective, :trailing_adjective => ref.trailing_adjective ) end end |
Instance Method Details
#compile(input) ⇒ Object
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/activefacts/cql/compiler.rb', line 104 def compile input include_language @string = input # The syntax tree created from each parsed CQL statement gets passed to the block. # parse_all returns an array of the block's non-nil return values. ok = parse_all(@string, :definition) do |node| trace :parse, "Parsed '#{node.text_value.gsub(/\s+/,' ').strip}'" do trace :lex, (proc { node.inspect }) begin ast = node.ast next unless ast trace :ast, ast.inspect ast.tree = node ast.constellation = @constellation ast.vocabulary = @vocabulary value = compile_definition ast trace :definition, "Compiled to #{value.is_a?(Array) ? value.map{|v| v.verbalise}*', ' : value.verbalise}" if value if value.is_a?(ActiveFacts::Metamodel::Topic) topic_flood() if @topic create_import_if_pending(value) @topic = value elsif ast.is_a?(Compiler::Vocabulary) topic_flood() if @topic @vocabulary = value @topic = @constellation.Topic(@vocabulary.name) end rescue => e # Augment the exception message, but preserve the backtrace start_line = @string.line_of(node.interval.first) end_line = @string.line_of(node.interval.last-1) lines = start_line != end_line ? "s #{start_line}-#{end_line}" : " #{start_line.to_s}" ne = StandardError.new("at line#{lines}, #{e..strip}") ne.set_backtrace(e.backtrace) raise ne end end topic_flood() if @topic end raise failure_reason unless ok vocabulary end |
#compile_definition(ast) ⇒ Object
216 217 218 |
# File 'lib/activefacts/cql/compiler.rb', line 216 def compile_definition ast ast.compile end |
#compile_file(filepath) ⇒ Object
54 55 56 57 58 59 60 61 62 |
# File 'lib/activefacts/cql/compiler.rb', line 54 def compile_file filepath old_filepath = @filepath @filepath = filepath File.open(filepath) do |f| compile(f.read) end @filepath = old_filepath @vocabulary end |
#compile_import(file, import_role, aliases) ⇒ Object
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/activefacts/cql/compiler.rb', line 148 def compile_import file, import_role, aliases saved_index = @index saved_block = @block saved_string = @string saved_input_length = @input_length old_filepath = @filepath @file = file @filepath = import_filepath(old_filepath, file) compile_import_file(@filepath, import_role) rescue => e ne = StandardError.new("In #{@filepath} #{e..strip}") ne.set_backtrace(e.backtrace) raise ne ensure @block = saved_block @index = saved_index @input_length = saved_input_length @string = saved_string @filepath = old_filepath nil end |
#compile_import_file(filepath, import_role) ⇒ Object
redefine in subsclass for different behaviour
183 184 185 186 187 188 |
# File 'lib/activefacts/cql/compiler.rb', line 183 def compile_import_file filepath, import_role # REVISIT: Save and use another @vocabulary for this file? File.open(filepath) do |f| compile_import_input(f.read, import_role) end end |
#compile_import_input(input, import_role) ⇒ Object
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/activefacts/cql/compiler.rb', line 190 def compile_import_input input, import_role topic_external_name = @file if existing_topic = @constellation.Topic[[topic_external_name]] # topic has already been loaded, just build import trace :import, "Topic #{@topic.topic_name} has already been loaded, skip reload" import = @constellation.Import( topic: @topic, precursor_topic: existing_topic, import_role: import_role, file_name: topic_external_name ) else # topic has not been loaded previously, import topic saved_topic = @topic topic_flood() if @topic @pending_import_topic = saved_topic @pending_import_role = import_role @pending_import_file_name = topic_external_name trace :import, "Importing #{@filepath} into #{@topic.topic_name}" do ok = parse_all(input, nil, &@block) end @topic = saved_topic end end |
#create_import_if_pending(new_topic) ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/activefacts/cql/compiler.rb', line 87 def create_import_if_pending new_topic if @pending_import_topic trace :import, "Topic #{@pending_import_topic.topic_name} imports #{new_topic.topic_name} as #{@pending_import_role} from file #{@pending_import_file_name}" @constellation.Import( topic: @pending_import_topic, precursor_topic: new_topic, import_role: @pending_import_role, file_name: @pending_import_file_name ) @pending_import_topic = nil @pending_import_role = '' @pending_import_file_name = '' end end |
#detect_language ⇒ Object
Load the appropriate natural language module
65 66 67 68 69 |
# File 'lib/activefacts/cql/compiler.rb', line 65 def detect_language @filepath =~ /.*\.(..)\.cql$/i language_code = $1 @language = LANGUAGES[language_code] || 'English' end |
#import_filepath(old_filepath, file) ⇒ Object
redefine in subsclass for different behaviour
173 174 175 176 177 178 179 180 |
# File 'lib/activefacts/cql/compiler.rb', line 173 def import_filepath(old_filepath, file) filepath = '' EXTENSIONS.each do |extension| filepath = File.dirname(old_filepath)+'/'+file+".#{extension}" break if File.exist?(filepath) end filepath end |
#include_language ⇒ Object
71 72 73 74 75 76 |
# File 'lib/activefacts/cql/compiler.rb', line 71 def include_language detect_language unless @langage require 'activefacts/cql/parser/Language/'+@language language_module = ActiveFacts::CQL.const_get(@language) extend language_module end |
#topic_flood ⇒ Object
Mark any new Concepts as belonging to this topic
79 80 81 82 83 84 85 |
# File 'lib/activefacts/cql/compiler.rb', line 79 def topic_flood @constellation.Concept.each do |key, concept| next if concept.topic trace :topic, "Colouring #{concept.describe} with #{@topic.topic_name}" concept.topic = @topic end end |
#unit?(s) ⇒ Boolean
220 221 222 223 224 225 |
# File 'lib/activefacts/cql/compiler.rb', line 220 def unit? s name = @constellation.Name[s] units = (!name ? [] : Array(name.unit) + Array(name.plural_named_unit)).uniq trace :units, "Looking for unit #{s}, got #{units.map{|u|u.name}.inspect}" units.size > 0 end |