# Copyright 2006 Instituto de Investigaciones Dr. José María Luis Mora / # Instituto de Investigaciones Estéticas. # See COPYING.txt and LICENSE.txt for redistribution conditions. # # D.R. 2006 Instituto de Investigaciones Dr. José María Luis Mora / # Instituto de Investigaciones Estéticas. # Véase COPYING.txt y LICENSE.txt para los términos bajo los cuales # se permite la redistribución. module KRLogic module DefFiles class Element; end class Section < Element; end class Line < Element; end class Element include RJBM::JAccess # Subclasses may create a Java interface which must extend the # Java interface mx.org.pescador.definitionsfile.DefFileElement. # Methods offered to Java from this superclass are: # origStr, line and inFile attr_accessor(:file, :line, :orig_str) alias_method(:origStr, :orig_str) @@all_elements = Array.new @@all_organized = false def Element.token @token end def Element.rule @rule end def Element.name @name end def Element.name=(name) @scan_for_str = name @name = self.unique_name(name) end def Element.regexp_for_val=(rfv) @regexp_for_val = rfv end def Element.regexp_for_val @regexp_for_val end def Element.make_token(regex, scan_order) tok_name = @name @token = Parser::Token.new(regex, scan_order, tok_name) end def Element.make_standard_token self.make_token(Regexp.new("\\b" + @scan_for_str + "\\b"), 100) end def Element.uses_token? if @token true else false end end def Element.make_index=(bool) @make_index = bool end def Element.make_index? if @make_index true else false end end def Element.scan_str(str_scanner) if @token s = @token.scan_str(str_scanner) if s s else nil end else nil end end def Element.setup @rule = Parser::Rule.new(@name) @@all_organized = false end def Element.setup_lines_and_sections Element.all_lines_and_sections.each do |e| e.setup end end def Element.all_elements self.organize_elements unless @@all_organized @@all_elements end def Element.all_tokenized_elements self.organize_elements unless @@all_organized @@all_tokened_elements end def Element.all_lines_and_sections self.organize_elements unless @@all_organized @@all_lines_and_sections end def initialize(args) @orig_str = args[:str] @line = args[:line] @file = args[:file] if (self.class.make_index?) @file.add_to_index(self) DefFiles.add_to_global_index(self) end @done = false j_bind if self.class.j_has_interface? end def done? @done end def done @done = true end def inFile # this method is meant to be called only from Java # Returns the JavaBridge representation of the file @file.j end private def Element.add_to_list(e) @@all_elements.push(e) @@all_organized = false e.instance_variable_set(:@token, nil) end def Element.unique_name(name) test_name = name.downcase list = (self.all_elements.map{|e| e.name ? e.name.downcase : nil }).compact if list.include?(test_name) ctr = 0 while list.include?(test_name) test_name = name.downcase + "_" + (++ctr).to_s end name + "_" + ctr.to_s else name end end def Element.organize_elements @@all_elements.sort! do |e1, e2| ord1 = (e1.uses_token? ? e1.token.scan_order : 10000) ord2 = (e2.uses_token? ? e2.token.scan_order : 10000) ord1 <=> ord2 end @@all_tokened_elements = @@all_elements.reject do |e| not e.uses_token? end @@all_lines_and_sections = @@all_elements.reject do |e| (e.superclass != Line) && (e.superclass != Section) end @@all_organized = true end end # Snippets # TODO: Add as class methods some code that is repeated in various Snippet rules class Snippet < Element attr_accessor(:val) def Snippet.make_standard_rule @rule = Parser::Rule.new(@name) @rule.code = </mu, 1000) self.regexp_for_val = /\<\%(.*)\%\>/mu self.setup self.make_standard_rule end class URI < Snippet self.name = "URI" self.make_token(/\b[a-zA-Z_]\w*:\w+/u, 1903) self.regexp_for_val = /(.*)/ self.setup self.make_standard_rule j_import( 'mx.org.pescador.krmodel.graphelements.Graph') attr_reader(:prefix, :localURIPart) def initialize(args) super(args) parse_result = Graph.parsePrettyURI(@val) @prefix = parse_result.prefix @localURIPart = parse_result.localURIPart end end class Integer < Snippet self.name = "Integer" self.make_token(/\b\d+\b/, 1904) self.regexp_for_val = /(.*)/ self.setup self.make_standard_rule end class Identifier < Snippet self.name = "Identifier" self.make_token(/\b[a-zA-Z_](\w|\.)*/u, 2000) self.regexp_for_val = /(.*)/ self.setup self.make_standard_rule def initialize(args) super(args) end end class KROperator < Snippet self.name = "KROperator" self.make_token(/-\>/, 1903) self.setup self.make_standard_rule end class KRRelRefOptions < Snippet self.name = "KRRelRefOptions" self.make_token(/\[(inv|nonInf)(, +(inv|nonInf))*?\]/, 1903) self.setup self.make_standard_rule attr_reader(:inv, :non_inf) def initialize(args) super(args) @inv = @orig_str.match(/\binv\b/) ? true : false @non_inf = @orig_str.match(/\bnonInf\b/) ? true : false end end class KRRelRefPartWithOptions < Snippet self.name = "KRRelRefPartWithOptions" self.setup @rule.code = <val[0..1].map{|arg| arg.orig_str}.join(' '), :line=>val[0].line, :file=>val[0].file }); result.id = val[0]; result.inv = val[1].inv; result.non_inf = val[1].non_inf} EOS attr_accessor(:id, :inv, :non_inf) end class LinkingKRRelRef < Snippet self.name = "LinkingKRRelRef" self.setup @rule.code = <val[0..-1].map{|arg| arg.orig_str}.join(' '), :line=>val[0].line, :file=>val[0].file }); result.val=[val[0], val[2]] } | #{Identifier.rule.name} #{KROperator.rule.name} #{KRRelRefPartWithOptions.rule.name} { result = #{self.to_s}.new({ :str =>val[0..-1].map{|arg| arg.orig_str}.join(' '), :line=>val[0].line, :file=>val[0].file }); result.val=[val[0], val[2]] } | #{KRRelRefPartWithOptions.rule.name} #{KROperator.rule.name} #{Identifier.rule.name} { result = #{self.to_s}.new({ :str =>val[0..-1].map{|arg| arg.orig_str}.join(' '), :line=>val[0].line, :file=>val[0].file }); result.val=[val[0], val[2]] } | #{KRRelRefPartWithOptions.rule.name} #{KROperator.rule.name} #{KRRelRefPartWithOptions.rule.name} { result = #{self.to_s}.new({ :str =>val[0..-1].map{|arg| arg.orig_str}.join(' '), :line=>val[0].line, :file=>val[0].file }); result.val=[val[0], val[2]] } ; EOS end class NewLine < Snippet self.name = "NewLine" self.make_token(/(\#.*?)*(\r\n|\n\r|\r|\n)+/, 1004) self.setup @rule.code = </, 1003) self.setup self.make_standard_rule end class Section < Element attr_accessor(:is_in, :index) attr_reader(:contents, :id) # Instance methods def add_contents(contents) @contents = contents @cont_index = Hash.new @contents.each_index do |i| e = @contents[i] cls = e.class raise "#{cls.name} not allowed in #{self.class.name}: line #{@line}, #{@file}." unless (self.class.allowed_contents.include?(e.class)) e.is_in = self e.index = i if @cont_index.has_key?(cls) @cont_index[cls].push(e) else @cont_index[cls] = [e] end end end def contained(cls, index=0) if @cont_index.has_key?(cls) @cont_index[cls][index] else nil end end def count_contained(cls) if @cont_index.has_key?(cls) @cont_index[cls].size else 0 end end def all_contained(cls) i = @cont_index[cls] i ? i : [] end def set_id(id) @id = id end # Class methods def Section.make_standard_name n = self.to_s.slice(/\w+$/) n[0,1] = n[0,1].upcase self.name=(n) end def Section.section_id_opts @section_id_opts end def Section.section_id_opts=(opts) @section_id_opts = opts end def Section.setup self.make_standard_name unless @name super self.make_standard_token self.make_rule end def Section.allowed_contents @allowed_contents end def Section.allowed_contents=(allowed) @allowed_contents = allowed end def Section.make_rule @rule = Parser::Rule.new(@name) sts = StartTagStart.rule.name ets = EndTagStart.rule.name te = TagEnd.rule.name nl = NewLine.rule.name rule_code_bits = Array.new @section_id_opts.each do |opt| if opt id = opt.rule.name rule_code_bit = "#{sts} #{@token.name} #{id} #{te} #{nl} section_content #{ets} #{@token.name} #{te} #{nl} { result = #{self.to_s}.new(val[1]); result.set_id(val[2]); result.add_contents(val[5]) }" else rule_code_bit = "#{sts} #{@token.name} #{te} #{nl} section_content #{ets} #{@token.name} #{te} #{nl} { result = #{self.to_s}.new(val[1]); result.add_contents(val[4]) }" end rule_code_bits.push(rule_code_bit) end @rule.code = < 0 args_code_bit = (opt.map {|arg| arg.rule.name }).join(" ") if @implied_directive rule_code_bit = <val[0..-2].map{|arg| arg.orig_str}.join(' '), :line=>val[0].line, :file=>val[0].file }); result.args = val[0..-2] } EOS else rule_code_bit = "#{token_bit} #{args_code_bit} #{nl} { result = #{self.to_s}.new(val[0]); result.args = val[1..-2] }" end else if @implied_directive raise "Attempt to define element with implied directive but no arguments: #{self.to_s}" else rule_code_bit = "#{token_bit} #{nl} { result = #{self.to_s}.new(val[0]) }" end end rule_code_bits.push(rule_code_bit) end @rule.code = <