class MODL::Parser::Parsed::ParsedPair
Class to represent a parsed grammar object
Attributes
array[RW]
final[RW]
key[RW]
key_lists[RW]
loaded[RW]
map[RW]
text[RW]
type[RW]
valueItem[RW]
Public Class Methods
new(global)
click to toggle source
# File lib/modl/parser/parsed.rb, line 209 def initialize(global) @global = global @needs_defref = true @final = false @file_importer = FileImporter.instance @loaded = false @array = nil @map = nil end
Public Instance Methods
enterModl_pair(ctx)
click to toggle source
# File lib/modl/parser/parsed.rb, line 295 def enterModl_pair(ctx) @type = 'pair' # default the type to an ordinary pair ctx_string = ctx.STRING @key = ctx_string.to_s unless ctx_string.nil? ctx_quoted = ctx.QUOTED unless ctx_quoted.nil? @key = ctx_quoted.to_s @key = Sutil.toptail(@key) # remove the quotes end raise InterpreterError, 'Invalid key - null, true, or false keys are not allowed.' if @key.nil? if @key.include?('%') || @key.include?('`') @key, new_value = RefProcessor.deref @key, @global unless @key.is_a?(String) raise InterpreterError, "Error: '" + @key.to_s + "' is an invalid key." if new_value.nil? @key = new_value.is_a?(String) ? new_value : new_value.text end raise InterpreterError, "Error: '" + @key.to_s + "' should de-ref to a string." unless key.is_a?(String) end @final = true if @key.upcase == @key modl_array = ctx.modl_array modl_map = ctx.modl_map modl_value_item = ctx.modl_value_item if !modl_array.nil? @array = ParsedArray.new @global modl_array.enter_rule(@array) elsif !modl_map.nil? @map = ParsedMap.new @global modl_map.enter_rule(@map) elsif !modl_value_item.nil? @valueItem = ParsedValueItem.new @global modl_value_item.enter_rule(@valueItem) end set_pair_type raise InterpreterError, 'Invalid keyword: ' + @key if @type == 'pair' && @key.start_with?('*') validate_key if @type == 'pair' || @type == 'hidden' # Type-specific processing case @type when 'class' ClassExtractor.extract(self, @global) when 'id' extract_value when 'name' extract_value when 'superclass' extract_value when 'allow' extract_value when 'keylist' KeylistExtractor.extract(self, @valueItem) if @valueItem KeylistExtractor.extract(self, @array) if @array when 'version' extract_value raise InterpreterError, 'Invalid MODL version: ' + @valueItem.value.primitive.text if @valueItem.value.primitive.number.nil? raise InterpreterError, 'Invalid MODL version: ' + @valueItem.value.primitive.number.num.to_s if @valueItem.value.primitive.number.num.is_a? Float raise InterpreterError, 'Invalid MODL version: ' + @valueItem.value.primitive.number.num.to_s if @valueItem.value.primitive.number.num.zero? raise InterpreterError, 'MODL version should be on the first line if specified.' if @global.has_pairs? @global.syntax_version = @valueItem.value.primitive.number.num when 'method' MethodExtractor.extract(self, @global) when 'transform' extract_transform @valueItem when 'import' files = @valueItem.extract_hash if @valueItem files = @array.extract_hash if @array @file_importer.import_files files, @global unless @global.in_condition? when 'index' IndexExtractor.extract(self, @global) when 'hidden' extract_value else extract_value end return if @global.in_condition? # Don't store pairs in conditionals until we evaluate the conditions if @key.start_with? '_' k = Sutil.tail(@key) existing = @global.pair(k) raise InterpreterError, 'Already defined ' + k + ' as final.' if existing&.final && @type != "import" raise InterpreterError, 'Cannot load multiple files after *LOAD instruction' if existing&.final && @type == "import" @global.pair(k, self) end existing = @global.pair(@key) raise InterpreterError, 'Already defined ' + @key + ' as final.' if existing&.final && @type != "import" raise InterpreterError, 'Cannot load multiple files after *LOAD instruction' if existing&.final && @type == "import" @global.pair(@key, self) end
extract_hash()
click to toggle source
Convert this object to a simple hash ready for JSON.generate
# File lib/modl/parser/parsed.rb, line 274 def extract_hash value = @array.extract_hash if @array value = @valueItem.extract_hash if @valueItem value = @map.extract_hash if @map @text = value return if @type == 'index' return if @type == 'hidden' return if @type == 'version' return if @type == 'class' return if @type == 'method' return if @type == 'import' return if @type == 'allow' return if @type == 'expect' formatted_key = Substitutions.process UnicodeEscapes.process @key {formatted_key => @text} end
find_property(key)
click to toggle source
# File lib/modl/parser/parsed.rb, line 219 def find_property(key) return self if key == @key return @map.find_property(key) if @map return @array.find_property(key) if @array return @valueItem.find_property(key) if @valueItem end
set_value(value)
click to toggle source
Set the appropriate field base on the value type
# File lib/modl/parser/parsed.rb, line 228 def set_value(value) if value.is_a? Array @map = nil @array = ParsedArray.new @global @array.abstractArrayItems = [] value.each do |item| array_item = ParsedArrayItem.new @global array_item.arrayValueItem = ParsedArrayValueItem.new @global array_item.arrayValueItem.primitive = ParsedPrimitive.new(@global) array_item.arrayValueItem.primitive.string = ParsedString.new(item) array_item.arrayValueItem.primitive.text = item @array.abstractArrayItems << array_item end @valueItem = nil @text = @array.extract_hash return elsif value.is_a?(ParsedPair) @map = value.map ? value.map : nil @array = value.array ? value.array : nil @valueItem = value.valueItem ? value.valueItem : nil return elsif value.is_a?(TrueClass) || value.is_a?(FalseClass) @map = nil @array = nil @valueItem = ParsedValueItem.new @global @valueItem.value = ParsedValue.new @global @valueItem.value.primitive = ParsedPrimitive.new(@global) if value @valueItem.value.primitive.trueVal = ParsedTrue.instance else @valueItem.value.primitive.falseVal = ParsedFalse.instance end @valueItem.value.primitive.text = value @valueItem.value.text = value @text = value return end value = value.extract_hash unless value.is_a?(String) || value.is_a?(Integer) @map = nil @array = nil @valueItem = ParsedValueItem.new @global @valueItem.value = ParsedString.new(value) @text = value end
Private Instance Methods
extract_transform(item)
click to toggle source
# File lib/modl/parser/parsed.rb, line 405 def extract_transform item @transform = item.value.primitive.string.string end
extract_value()
click to toggle source
# File lib/modl/parser/parsed.rb, line 398 def extract_value item = @valueItem @text = item.value.text if item.is_a?(ParsedValueItem) && item.value @text = item.valueItem.value.text if item.is_a?(ParsedPair) invoke_deref end
invoke_deref()
click to toggle source
# File lib/modl/parser/parsed.rb, line 421 def invoke_deref return unless @needs_defref && !@text.nil? && @text.is_a?(String) && @text.include?('%') @needs_defref = false @text, new_value = RefProcessor.deref @text, @global if new_value.is_a? ParsedMap @map = new_value @valueItem = nil @array = nil elsif new_value.is_a? ParsedArray @array = new_value @valueItem = nil @map = nil elsif new_value.is_a? ParsedValueItem @valueItem = new_value elsif new_value.nil? set_value @text elsif new_value.is_a? ParsedPair set_value @text if @text set_value new_value if @text.nil? elsif new_value.is_a? String set_value @text else set_value(new_value) end end
set_pair_type()
click to toggle source
Set the pair type if its a 'special' type
# File lib/modl/parser/parsed.rb, line 450 def set_pair_type @type = 'class' if @key == '*c' || @key == '*class' if @key == '*C' || @key == '*CLASS' @type = 'class' @key = @key.downcase end @type = 'id' if @key == '*i' || @key == '*id' @type = 'name' if @key == '*n' || @key == '*name' @type = 'name' if @key == '*N' || @key == '*NAME' @type = 'superclass' if @key == '*S' || @key == '*SUPERCLASS' @type = 'superclass' if @key == '*s' || @key == '*superclass' @type = 'keylist' if @key == '*a' || @key == '*assign' @type = 'version' if @key == '*V' || @key == '*VERSION' @type = 'method' if @key == '*m' || @key == '*method' @type = 'transform' if @key == '*t' || @key == '*transform' if @key == '*L' || @key == '*LOAD' @key = @key.downcase @type = 'import' if @array @global.freeze_max_files(@array.abstractArrayItems.length) elsif @valueItem&.value&.array @global.freeze_max_files(@valueItem&.value&.array.abstractArrayItems.length) elsif @valueItem&.value&.nbArray @global.freeze_max_files(@valueItem&.value&.nbArray.arrayItems.length) else @global.freeze_max_files(1) end end if @key == '*l' || @key == '*load' @type = 'import' end @type = 'index' if @key == '?' @type = 'hidden' if @key.start_with? '_' @type = 'allow' if @key.downcase == '*allow' end
validate_key()
click to toggle source
# File lib/modl/parser/parsed.rb, line 409 def validate_key invalid_chars = "£!$@-+'*#^&" invalid_chars.each_char do |c| next unless @key.include?(c) raise InterpreterError, 'Invalid key - "' + c + '" character not allowed: ' + @key end key = @key.start_with?('_') ? Sutil.tail(@key) : @key raise InterpreterError, 'Invalid key - "' + key + '" - entirely numeric keys are not allowed: ' + @key if key == key.to_i.to_s end