lib/activefacts/cql/CQLParser.treetop in activefacts-0.7.3 vs lib/activefacts/cql/CQLParser.treetop in activefacts-0.8.5

- old
+ new

@@ -3,108 +3,129 @@ # Parse rules relating to high-level CQL definitions and constraints. # # Copyright (c) 2009 Clifford Heath. Read the LICENSE file. # module ActiveFacts - grammar CQL - include LexicalRules - include Language # One of the language modules provides this module - include Expressions - include Concepts - include DataTypes - include FactTypes + module CQL + grammar CQL + include LexicalRules + include Language # One of the language modules provides this module + include Expressions + include Terms + include Concepts + include ValueTypes + include FactTypes + include Context - rule cql_file - s seq:definition* - { - def definitions - seq.elements.map{|e| - e.value rescue $stderr.puts "Can't call value() on #{e.inspect}" - } - end - } - end + rule cql_file + s seq:definition* + { + def definitions + seq.elements.map{|e| + e.value rescue $stderr.puts "Can't call value() on #{e.inspect}" + } + end + } + end - # Each definition has a value() method that returns an array like - # either [name, [kind, definition]] or [name, kind]: - rule definition - vocabulary_definition - / import_definition - / constraint - / concept - end + # Each definition has a value() method that returns an array like + # either [name, [kind, definition]] or [name, kind]: + rule definition + vocabulary_definition + / import_definition + / prescan + / constraint + / unit_definition + / concept + end - rule vocabulary_definition - s vocabulary S id s ';' s - { - def value - [ id.text_value, [ :vocabulary ] ] - end - } - end + rule vocabulary_definition + s vocabulary S id s ';' s &{|e| input.context.vocabulary(e[3].text_value); true } + { + def value + [ id.value, [ :vocabulary ] ] + end + } + end - rule import_definition - s import S id alias_list ';' s - { - def value - puts "import #{id.text_value}: not implemented" - [ id.text_value, [ :import ], alias_list.value ] - end - } - end + rule import_definition + s import S id alias_list ';' s + { + def value + puts "import #{id.value}: not implemented" + [ id.value, [ :import ], alias_list.value ] + end + } + end - # REVISIT: Need a way to define equivalent readings for fact types here (and in the metamodel) - rule alias_list - ( s ',' s alias S aliase_from:id S as S alias_to:id s )* - { - def value - elements.inject({}){|h, e| h[e.aliase_from.text_value] = e.alias_to; h } - end - } - end + # REVISIT: Need a way to define equivalent readings for fact types here (and in the metamodel) + rule alias_list + ( s ',' s alias S aliased_from:id S as S alias_to:id s )* + { + def value + elements.inject({}){|h, e| h[e.aliased_from.value] = e.alias_to; h } + end + } + end - rule constraint - subset_constraint / - equality_constraint / - set_constraint / - presence_constraint - # REVISIT: / value_constraint - end + rule constraint + subset_constraint / + equality_constraint / + set_constraint / + presence_constraint + # REVISIT: / value_constraint + end - # presence constraint: - rule presence_constraint - s 'each' s ('combination' S)? role_list s 'occurs' s quantifier s 'time' s 'in' s - readings_list s - ';' s - { def value; [ nil, [ :constraint, :presence, role_list.roles, quantifier.value, readings_list.value ] ]; end } - end + # presence constraint: + rule presence_constraint + s 'each' s ('combination' S)? role_list s 'occurs' s quantifier s 'time' s 'in' s + readings_list s + c:context? ';' s + { def value; [ nil, [ :constraint, :presence, role_list.roles, quantifier.value, readings_list.value, c.empty? ? nil : c.value ] ]; end } + end - rule subset_constraint - s readings s only s if s r2:readings s ';' s - { def value; [ nil, [ :constraint, :subset, readings.value, r2.value ] ]; end } - end + # set (exclusion, mandatory exclusion, complex equality) constraint + rule set_constraint + s 'for' s 'each' s role_list s quantifier s 'of' s 'these' s 'holds' s ':' s + readings_list s + c:context? ';' s + { def value; [ nil, [ :constraint, :set, role_list.roles, quantifier.value, readings_list.value, c.empty? ? nil : c.value ] ]; end } + / + s either? s r1:readings s or s r2:readings exclusion:(but s not s both s)? c:context? ';' s + { def value; + [ nil, [ :constraint, :set, + nil, # No roles names, rely on the join + exclusion.text_value.empty? ? + [1, nil] : # At least one (meaning 1 or 2/more) + [1,1], # Exactly one (1 and only 1) + [r1.value, r2.value], + c.empty? ? nil : c.value + ] ]; + end + } + end - # set (exclusion, mandatory exclusion, complex equality) constraint - rule set_constraint - s 'for' s 'each' s role_list s quantifier s 'of' s 'these' s 'holds' s ':' s - readings_list s - ';' s - { def value; [ nil, [ :constraint, :set, role_list.roles, quantifier.value, *readings_list.value ] ]; end } - end + rule subset_constraint + s readings s only s if s r2:readings s + c:context? ';' s + { def value; [ nil, [ :constraint, :subset, [readings.value, r2.value], c.empty? ? nil : c.value ] ]; end } + end - rule equality_constraint - s readings s tail:( if s and s only s if s readings s)+ ';' s - { def value; [ nil, [ :constraint, :equality, *([readings.value] + tail.elements.map{|e| e.readings.value }) ] ]; end } - end + rule equality_constraint + s readings s tail:( if s and s only s if s readings s)+ + c:context? ';' s + { def value; [ nil, [ :constraint, :equality, [readings.value] + tail.elements.map{|e| e.readings.value }, c.empty? ? nil : c.value ]]; end } + end - rule readings_list - readings tail:( ',' s readings )* - { def value; [readings.value]+tail.elements.map{|e| e.readings.value }; end } - end + rule readings_list + readings tail:( ',' s readings )* + { def value; [readings.value]+tail.elements.map{|e| e.readings.value }; end } + end - rule readings - reading s tail:( and s reading s )* - { def value; [reading.value]+tail.elements.map{|e| e.reading.value }; end } - end + rule readings + reading s tail:( and s reading s )* + { def value; [reading.value]+tail.elements.map{|e| e.reading.value }; end } + end + end end end