Class: Semantic::Functions
- Inherits:
- 
      Hash
      
        - Object
- Hash
- Semantic::Functions
 
- Defined in:
- ../lib/semantic_functions.rb
Overview
Parsing and storing of the syntactic functions. The Functions class subclasses the Hash class. It maps nonterminal symbols to its expansion hashes of the semantic functions:
  { 
    "symbol1" => { "expansion1_1"=>[ AttrFn, AttrFn ... ], "expansion1_2"=>[ AttrFn, AttrFn ... ], ... },
    "symbol2" => { "expansion2_1"=>[ AttrFn, AttrFn ... ], "expansion2_2"=>[ AttrFn, AttrFn ... ], ... },     
    ...
  }Instance Attribute Summary (collapse)
- 
  
    
      - (Object) attributes 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    Attribute identifier array. 
Class Method Summary (collapse)
- 
  
    
      + (Object) extract_args(text) 
    
    
  
  
  
  
  
  
  
  
  
    Extract all arguments from the body of the semantic function. 
- 
  
    
      + (Object) make_proc(text) 
    
    
  
  
  
  
  
  
  
  
  
    Compile the semantic function previously processed by the extract_args and replace_args. 
- 
  
    
      + (Object) match_key(rulealt) 
    
    
  
  
  
  
  
  
  
  
  
    Convert the Mapper::RuleAlt into the representing string (the expansion key). 
- 
  
    
      + (Object) replace_args(text_orig, args) 
    
    
  
  
  
  
  
  
  
  
  
    Replace argument identifiers in the source of the semantic function by the _[i] notation. 
Instance Method Summary (collapse)
- 
  
    
      - (Functions) initialize(semantic = nil) 
    
    
  
  
  
    constructor
  
  
  
  
  
  
  
    Load the semantic file. 
- 
  
    
      - (Object) new_attr_ref(text) 
    
    
  
  
  
  
  
  
  
  
  
    Convert the textual representation of the attribute to the AttrRef (the inversion is done by the render_attr method). 
- 
  
    
      - (Object) node_expansion(symbol, expansion) 
    
    
  
  
  
  
  
  
  
  
  
    Search for the appropriate semantic functions by the particular nonterminal symbol and the RuleAlt expansion. 
- 
  
    
      - (Object) render_attr(ref) 
    
    
  
  
  
  
  
  
  
  
  
    Convert the AttrRef to the textual representation of the attribute (the inversion is done by the new_attr_ref). 
Constructor Details
- (Functions) initialize(semantic = nil)
Load the semantic file. The file has to follow this form:
  symbol1:
    expansion1:
      result1_1 : function1_1
      result1_2 : function1_2
      ...
      result1_N1 : function1_N1
    expansion2:
      result2_1 : function2_1
      ...
      result2_N2 : function2_N2
    ...
    expansionM:
      ...
   symbol2:
   ...
   symbolP:
     ...
where:
   * symbol ... a nonterminal symbol defined by the ABNF grammar (see Mapper::Grammar)
   * expansion ... the expansion of the symbol defined by the grammar. 
                 All terminal symbols are matched by the '$' character. 
                 For instance, the ABNF rule:
                 if-statement = "if(" condition ") {" block "} else {" block "}"
                 is represented by:
                 if-statement:
                   $ condition $ block $ block $:
                 There is another special character '*' which matches all expansions.
   * result ... the semantic attribute of some symbol defined by the semantic function.
              It has the form:
                node.attribute
              where attribute is the identifier of the attribute and node is either
              p (parent node) or ci (child node, i is the index of the child beginning from 0).
              There are reserved attribute identifiers:
              _text  .. represents the text of the terminal symbol or the symbol identifier
                        of the nonterminal symbol
              _valid .. the boolean attribute which restricts the usage of the expansion 
                        (see AttrGrDepthFirst class for details)
   * function ... the semantic function using node.attribute arguments, using the Ruby syntax.
Notes: The ‘_’ identifier is reserved and cannot be used as the attribute name or another variable name. If the attribute’s ‘nil’ value means ‘not defined’. Do not use ‘nil’ as a result of a semantic function.
| 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | # File '../lib/semantic_functions.rb', line 69 def initialize semantic=nil super() @attributes = AttrIndices.clone # default ctor return if semantic.nil? # parsing ctor yaml = YAML::load( semantic ) yaml.keys.sort.each do |symbol| rules = yaml[symbol] newrules = {} rules.each_pair do |expansion,funcs| batch = [] funcs.each_pair do |dest,body| target = new_attr_ref dest args = Functions.extract_args( body ) inputs = args.map { |arg| new_attr_ref arg } fn = Functions.make_proc( Functions.replace_args(body,args) ) batch << AttrFn.new( fn, target, inputs, body ) end newrules[expansion] = batch end store( symbol, newrules ) end end | 
Instance Attribute Details
- (Object) attributes (readonly)
Attribute identifier array. It contains all attribute identifiers appearing on both the left and right sides of semantic fuctions. For example:
  [ '_text', '_valid', 'cont', 'def', 'span' ]
Note that reserved identifiers beginning with ‘_’ are always present.
| 112 113 114 | # File '../lib/semantic_functions.rb', line 112 def attributes @attributes end | 
Class Method Details
+ (Object) extract_args(text)
Extract all arguments from the body of the semantic function.
| 132 133 134 | # File '../lib/semantic_functions.rb', line 132 def Functions.extract_args text text.scan( /[\w]+\.[\w]+/ ).uniq end | 
+ (Object) make_proc(text)
Compile the semantic function previously processed by the extract_args and replace_args.
| 144 145 146 | # File '../lib/semantic_functions.rb', line 144 def Functions.make_proc text eval( "proc { |_| #{text} }" ) end | 
+ (Object) match_key(rulealt)
Convert the Mapper::RuleAlt into the representing string (the expansion key).
| 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | # File '../lib/semantic_functions.rb', line 116 def Functions.match_key rulealt result = rulealt.map do |token| case token.type when :literal '$' when :symbol token.data else raise 'Semantic::Functions wrong token type' end end result.join ' ' end | 
+ (Object) replace_args(text_orig, args)
Replace argument identifiers in the source of the semantic function by the _[i] notation.
| 137 138 139 140 141 | # File '../lib/semantic_functions.rb', line 137 def Functions.replace_args( text_orig, args ) text = text_orig.clone args.each_with_index { |a,i| text.gsub!( a, "_[#{i}]" ) } text end | 
Instance Method Details
- (Object) new_attr_ref(text)
Convert the textual representation of the attribute to the AttrRef (the inversion is done by the render_attr method). For instance: ‘c1._text’ -> AttrRef.new( 2, 0 ). Note it modifies @attributes if given a new attribute identifier.
| 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | # File '../lib/semantic_functions.rb', line 159 def new_attr_ref text all,node,attr = /^([^.]*)\.([^.].*)$/.match( text ).to_a raise "Semantic::Functions wrong node/attribute '#{text}'" if all.nil? idx = @attributes.index attr if idx.nil? idx = @attributes.size @attributes.push attr end return AttrRef.new( 0, idx ) if node == 'p' raise "Semantic::Functions wrong node '#{text}'" unless node.size > 1 and /^c/ =~ node return AttrRef.new( node[1,node.size-1].to_i+1, idx ) end | 
- (Object) node_expansion(symbol, expansion)
Search for the appropriate semantic functions by the particular nonterminal symbol and the RuleAlt expansion.
| 149 150 151 152 153 154 | # File '../lib/semantic_functions.rb', line 149 def node_expansion( symbol, expansion ) node = fetch(symbol.data, nil) return [] if node.nil? batch = deep_copy( node.fetch( Functions.match_key(expansion), [] ) ) return batch.concat( deep_copy( node.fetch( '*', [] ) ) ) end | 
- (Object) render_attr(ref)
Convert the AttrRef to the textual representation of the attribute (the inversion is done by the new_attr_ref). For example: AttrRef.new( 0, 1 ) -> ‘p._valid’.
| 177 178 179 | # File '../lib/semantic_functions.rb', line 177 def render_attr ref "#{ ref.node_idx==0 ? 'p' : 'c'+(ref.node_idx-1).to_s }.#{ @attributes[ ref.attr_idx ] }" end |