# # ActiveFacts CQL Parser. # Parse rules the English syntax of CQL. # # Copyright (c) 2009 Clifford Heath. Read the LICENSE file. # module ActiveFacts module CQL grammar English # >>>>>>>>>>>>>>>>>>>> Object Types <<<<<<<<<<<<<<<<<<<< # The pattern to introduce a Value Type rule written_as s 'is' s 'written' S as s end # The pattern to introduce an Entity Type rule identified_by identified s by s end rule basetype_expression is s i:( independent s )? identification end # The pattern to introduce an Entity Subtype rule subtype_prefix 'is' s 'a' s ('kind'/'subtype') s 'of' S end rule subtype_expression subtype_prefix i:( independent s )? supertype_list ident:identification? end # The pattern to introduce an objectified fact type with implicit identification rule is_where is s i:(independent s)? where { def independent; !i.empty?; end } end rule in_which # Introduce an objectification step where / # Old syntax in s which # preferred syntax end # Units conversion keyword rule conversion converts s a:(approximately s)? to s { def approximate? !a.empty? end } end # >>>>>>>>>>>>>>>>>>>> Constraints <<<<<<<<<<<<<<<<<<<< # External presence constraint syntax: rule each_occurs_in_clauses s 'each' s ('combination' S)? role_list s occurs s quantifier s 'time' 's'? s enforcement 'in' s clauses_list s c:context_note? ';' { def role_list_ast role_list.ast end def quantifier_ast quantifier.ast end def clauses_ast clauses_list.ast end } end # Alternate external presence constraint syntax: rule either_or s either? s r1:clauses s or s r2:clauses c:context_note? enforcement ';' { def role_list_ast nil end def quantifier_ast Compiler::Quantifier.new(1, nil) end def clauses_ast [r1.ast, r2.ast] end } end # Exclusion (at most one) and mandatory exclusion (exactly one) constraint syntax: rule for_each_how_many s 'for' s 'each' s role_list s quantifier s 'of' s 'these' s 'holds' s enforcement ':' s clauses_list s c:context_note? ';' { def role_list_ast role_list.ast end def quantifier_ast quantifier.ast end def clauses_ast clauses_list.ast end } end # Alternate mandatory exclusion constraint syntax: rule either_or_not_both s either? s r1:clauses s or s r2:clauses but s not s both s c:context_note? enforcement ';' { def role_list_ast nil end def quantifier_ast Compiler::Quantifier.new(1, 1) end def clauses_ast [r1.ast, r2.ast] end } end # Subset constraint using "A only if B" syntax rule a_only_if_b s clauses s only s if s r2:clauses s c:context_note? enforcement ';' end rule only_if only s if s end # Subset constraint using "if A then B" syntax rule if_b_then_a s if s clauses s then s r2:clauses s c:context_note? enforcement ';' end # Equality constraint syntax: rule if_and_only_if s clauses s tail:( if s and s only s if s clauses s)+ c:context_note? enforcement ';' end # During the prescan we need to know where terms in a role list finish. # This rule matches any non-term expressions that may follow a role list. rule role_list_constraint_followers occurs s quantifier s 'time' end # >>>>>>>>>>>>>>>>>>>> Quantifiers <<<<<<<<<<<<<<<<<<<< rule quantifier ( each s { def value; [1, nil]; end } / some s { def value; nil; end } # REVISIT: "Some" means that any prior occurrence of this role player is to be ignored; this is a new occurrence # "that" on the other hand means that this role player was *previously* designated using "some". # These distinctions are lost here / that s { def value; nil; end } / one s { def value; [1, 1]; end } / no s { def value; [0, 0]; end } / exactly s quantity { def value; q = quantity.value; [q, q]; end } / at s least s quantity most:( and s at s most s q:quantity )? { def value; [ quantity.value, most.empty? ? nil : most.q.value ] end } / at s most s quantity { def value; [ nil, quantity.value ]; end } / from s numeric_range s { def value; numeric_range.value; end } # / either_all_or_none s { def value; [ -1, 1 ]; end } ) { def ast v = value Compiler::Quantifier.new(v[0], v[1]) end } end # rule either_all_or_none either s all s or s ( none / no ) end rule quantity one s { def value; 1; end } / number s { def value; number.value; end } end # >>>>>>>>>>>>>>>>>>>> Context Notes <<<<<<<<<<<<<<<<<<<< rule as_agreed_by s as s 'agreed' s d:('on' S date)? by s agents { def value; [ d.empty? ? nil : d.date.value, agents.value ]; end } end rule date s d:(!(by/')') .)+ { def value; d.text_value.strip; end } end rule agents s h:agent s t:(',' s !context_type agent s)* { def value; [h.text_value] + t.elements.map{|e| e.agent.text_value }; end def node_type; :linking; end } end rule agent id (s id)* end rule negative_prefix s it s is s not s the s case s that s end rule agg_of of end rule agg_in in end rule restricted_to 'restricted' s 'to' s !alphanumeric end # any is optionally used in an identifying role_list rule any one / a end # >>>>>>>>>>>>>>>>>>>> Internal vocabulary <<<<<<<<<<<<<<<<<<<< rule a ('a' !alphanumeric /'an' !alphanumeric) end rule all 'all' !alphanumeric end rule ascending 'ascending' !alphanumeric end rule at 'at' !alphanumeric end rule both 'both' !alphanumeric end rule converts 'converts' !alphanumeric end rule descending 'descending' !alphanumeric end rule each 'each' !alphanumeric end rule either 'either' !alphanumeric end rule entity 'entity' !alphanumeric end rule exactly 'exactly' !alphanumeric end rule from 'from' !alphanumeric end rule includes 'includes' !alphanumeric end rule least 'least' !alphanumeric end rule matches 'matches' !alphanumeric end rule most 'most' !alphanumeric end rule no 'no' !alphanumeric end rule none 'none' !alphanumeric end rule not 'not' !alphanumeric end rule occurs 'occurs' !alphanumeric end rule one 'one' !alphanumeric end rule some 'some' !alphanumeric end # >>>>>>>>>>>>>>>>>>>> External vocabulary <<<<<<<<<<<<<<<<<<<< rule according_to 'according' S to end rule acyclic 'acyclic' !alphanumeric end rule alias 'alias' !alphanumeric end rule and 'and' !alphanumeric end rule antisymmetric 'antisymmetric' !alphanumeric end rule approximately 'approximately' !alphanumeric end rule as 'as' !alphanumeric end rule as_opposed_to as s 'opposed' S to end rule asymmetric 'asymmetric' !alphanumeric end rule because 'because' !alphanumeric end rule but 'but' !alphanumeric end rule by 'by' !alphanumeric end # fix? Used in 'returning' for ordering rule case 'case' !alphanumeric end rule definitely 'definitely' !alphanumeric end rule ephemera 'ephemera' !alphanumeric end rule false 'false' !alphanumeric end rule feminine 'feminine' !alphanumeric end rule identified ('known'/'identified') !alphanumeric end rule if 'if' !alphanumeric end rule in 'in' !alphanumeric end rule import 'import' !alphanumeric end rule independent 'independent' !alphanumeric end rule stronglyintransitive 'stronglyintransitive' !alphanumeric end rule intransitive 'intransitive' !alphanumeric end rule irreflexive 'irreflexive' !alphanumeric end rule is 'is' !alphanumeric end rule it 'it' !alphanumeric end rule its 'its' !alphanumeric end rule masculine 'masculine' !alphanumeric end rule maybe 'maybe' !alphanumeric end rule only 'only' !alphanumeric end rule or 'or' !alphanumeric end rule of 'of' !alphanumeric end rule ordering_prefix by s (ascending/descending)? s end rule otherwise 'otherwise' !alphanumeric end rule partitioned 'partitioned' !alphanumeric end rule personal 'personal' !alphanumeric end rule radix_point '.' end rule reflexive 'reflexive' !alphanumeric end rule returning 'returning' !alphanumeric end rule separate 'separate' !alphanumeric end rule so_that 'so' S that end rule static 'static' !alphanumeric end rule symmetric 'symmetric' !alphanumeric end rule that 'that' !alphanumeric end rule the 'the' !alphanumeric end rule then 'then' !alphanumeric end rule to 'to' !alphanumeric end rule to_avoid to s 'avoid' !alphanumeric end rule transient 'transient' !alphanumeric end rule transitive 'transitive' !alphanumeric end rule true 'true' !alphanumeric end rule vocabulary 'vocabulary' !alphanumeric end rule where 'where' !alphanumeric end rule which 'which' !alphanumeric end rule was 'was' !alphanumeric end rule who 'who' !alphanumeric end end end end