Module: WLang::RuleSet::Imperative

Defined in:
lib/wlang/rulesets/imperative_ruleset.rb

Overview

Imperative ruleset, providing special tags to iterate and instantiate conditionaly.

For an overview of this ruleset, see the wlang specification file.

Constant Summary

U =
WLang::RuleSet::Utils
EACH_REGEXP =

Regular expression for #1 in *{wlang/hosted}{...}

/^([^\s]+)((\s+(using\s+([_a-z]+)))?(\s+(as\s+([a-z]+(,\s+[a-z]+)*)))?)?$/
DEFAULT_RULESET =

Default mapping between tag symbols and methods

{'?' => :conditional, '*' => :enumeration}

Class Method Summary (collapse)

Class Method Details

+ (Object) conditional(parser, offset)

Conditional as ?{wlang/hosted}{...}{...}

(third block is optional) Instantiates #1, looking for an expression in the hosting language. Evaluates it, looking for a boolean value (according to boolean semantics of the hosting language). If true, instantiates #2, otherwise instantiates #3 if present.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/wlang/rulesets/imperative_ruleset.rb', line 29

def self.conditional(parser, offset)
  expression, reached = parser.parse(offset, "wlang/hosted")
  value = parser.evaluate(expression)
  if value
    then_block, reached = parser.parse_block(reached)
    if parser.has_block?(reached)
      else_block, reached = parser.parse_block(reached, "wlang/dummy")
    end          
    [then_block, reached]
  else
    then_block, reached = parser.parse_block(reached, "wlang/dummy")
    else_block = ""
    if parser.has_block?(reached)
      else_block, reached = parser.parse_block(reached)
    end          
    [else_block, reached]
  end
end

+ (Object) enumeration(parser, offset)

Enumeration as *{wlang/hosted using each as x}{...}{...}

(third block is optional) Instantiates #1, looking for an expression in the hosting language. Evaluates it, looking for an enumerable. Iterates all its elements, instanciating #2 for each of them (the iterated value is set under name x in the scope). If #3 is present, it is instantiated between elements.



66
67
68
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/wlang/rulesets/imperative_ruleset.rb', line 66

def self.enumeration(parser, offset)
  expression, reached = parser.parse(offset, "wlang/hosted")
    
  # decode 'wlang/hosted using each as x' expression
  hash = U.expr(:expr,
                ["using", :var, false],
                ["as", :multi_as, false]).decode(expression, parser)
  hash[:using] = "each" unless hash[:using]
  hash[:as] = [] unless hash[:as]
  parser.syntax_error(offset, "invalid loop expression '#{expression}'") if hash.nil?
    
  # evaluate 'wlang/hosted' sub-expression
  value = hash[:expr]
  if value.nil?
    expression, reached = parser.parse_block(reached, "wlang/dummy")
    expression, reached = parser.parse_block(reached, "wlang/dummy") if parser.has_block?(reached)
    ["",reached]
  else
    raise "Enumerated value #{value} does not respond to #{hash[:using]}"\
      unless value.respond_to?(hash[:using])

    # some variables
    iterator, names = hash[:using].to_sym, hash[:as]
    buffer = parser.factor_buffer
    
    # wlang start index of each block
    block2, block3, theend = reached, nil, nil # *{}{block2}{block3}theend
    first = true

    # iterate now
    value.send iterator do |*args|
      if not(first) and parser.has_block?(block3)
        # parse #3, positioned at reached after that
        parsed, theend = parser.parse_block(block3)
        parser.append_buffer(buffer, parsed, true)
      end
  
      # install arguments and parse block2, positioned at block3 
      parser.branch_scope(merge_each_args(names, args)) {
        parsed, block3 = parser.parse_block(block2)
        parser.append_buffer(buffer, parsed, true)
      }
      first = false
    end

    # Empty array special case
    unless block3
      parsed, block3 = parser.parse_block(block2, "wlang/dummy")
    end

    # Singleton array special case
    unless theend
      if parser.has_block?(block3)
        parsed, theend = parser.parse_block(block3, "wlang/dummy")
      else
        theend = block3
      end
    end
    [buffer, theend]
  end
    
end

+ (Object) merge_each_args(names, args)

Install args on the parser



49
50
51
52
53
54
55
56
# File 'lib/wlang/rulesets/imperative_ruleset.rb', line 49

def self.merge_each_args(names, args)
  hash = {}
  size = names.length>args.length ? args.length : names.length
  0.upto(size-1) do |i|
    hash[names[i]] = args[i]
  end
  hash
end