class KaiserRuby::Parser
Parser
class goes through the Rockstar code provided and generates an intermediate tree from which we can output a proper Ruby program
Constants
- ADDITION_KEYWORDS
- AND_KEYWORDS
- ASSIGNMENT_FIRST_KEYWORDS
- ASSIGNMENT_SECOND_KEYWORDS
- BREAK_KEYWORDS
- COMMON_VARIABLE_KEYWORDS
- COMPARISON_KEYWORDS
- CONTINUE_KEYWORDS
- DECREMENT_FIRST_KEYWORDS
- DECREMENT_SECOND_KEYWORDS
- DIVISION_KEYWORDS
- ELSE_KEYWORDS
- EQUALITY_KEYWORDS
- FALSE_TYPE
- FUNCTION_CALL_KEYWORDS
- FUNCTION_CALL_SEPARATORS
- FUNCTION_KEYWORDS
- FUNCTION_RESTRICTED_KEYWORDS
- FUNCTION_SEPARATORS
- GTE_KEYWORDS
- GT_KEYWORDS
- IF_KEYWORDS
- INCREMENT_FIRST_KEYWORDS
- INCREMENT_SECOND_KEYWORDS
- INEQUALITY_KEYWORDS
- LET_ASSIGNMENT_FIRST_KEYWORDS
- LET_ASSIGNMENT_SECOND_KEYWORDS
- LISTEN_KEYWORDS
- LISTEN_TO_KEYWORDS
- LOGIC_KEYWORDS
- LTE_KEYWORDS
- LT_KEYWORDS
- MATH_OP_KEYWORDS
- MATH_TOKENS
- MULTIPLICATION_KEYWORDS
- MYSTERIOUS_TYPE
- NOR_KEYWORDS
- NOT_KEYWORDS
- NULL_TYPE
- OR_KEYWORDS
- POETIC_NUMBER_CONTRACTIONS
- POETIC_NUMBER_KEYWORDS
- POETIC_STRING_KEYWORDS
- POETIC_TYPE_KEYWORDS
- POETIC_TYPE_LITERALS
- PRINT_KEYWORDS
- PRONOUN_KEYWORDS
- RESERVED_KEYWORDS
- RETURN_KEYWORDS
- SUBTRACTION_KEYWORDS
- TRUE_TYPE
- UNTIL_KEYWORDS
- WHILE_KEYWORDS
Attributes
lines[R]
raw_input[R]
tree[R]
Public Class Methods
new(input)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 72 def initialize(input) @raw_input = input @lines = input.gsub(/\(\n.*?\)/m, "\n").split(/\n/) # eat multiline comments end
Public Instance Methods
add_to_tree(object)
click to toggle source
private
# File lib/kaiser_ruby/parser.rb, line 699 def add_to_tree(object) object.extend(Hashie::Extensions::DeepLocate) object[:current_scope] = @current_scope.last object[:nesting] = @nesting @tree << object end
consume_function_calls(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 400 def consume_function_calls(string) if string =~ prepared_regexp(FUNCTION_CALL_KEYWORDS) words = string.split prepared_regexp(FUNCTION_RESTRICTED_KEYWORDS) found_string = words.select { |w| w =~ /\btaking\b/ }.first @function_temp << found_string string = string.gsub(found_string, " func_#{@function_temp.count - 1} ") end string end
matches_all?(words, rxp)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 724 def matches_all?(words, rxp) regexp = rxp.is_a?(Regexp) ? rxp : prepared_regexp(rxp) words.all? { |w| w =~ regexp } end
matches_any?(words, rxp)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 719 def matches_any?(words, rxp) regexp = rxp.is_a?(Regexp) ? rxp : prepared_regexp(rxp) words.any? { |w| w =~ regexp } end
matches_consecutive?(words, first_rxp, second_rxp)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 729 def matches_consecutive?(words, first_rxp, second_rxp) first_idx = words.index { |w| w =~ prepared_regexp(first_rxp) } second_idx = words.index { |w| w =~ prepared_regexp(second_rxp) } !second_idx.nil? && !first_idx.nil? && second_idx.to_i - first_idx.to_i == 1 end
matches_first?(words, rxp)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 736 def matches_first?(words, rxp) words.index { |w| w =~ prepared_regexp(rxp) }&.zero? end
matches_separate?(words, first_rxp, second_rxp)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 744 def matches_separate?(words, first_rxp, second_rxp) first_idx = words.index { |w| w =~ prepared_regexp(first_rxp) } second_idx = words.index { |w| w =~ prepared_regexp(second_rxp) } !second_idx.nil? && !first_idx.nil? && second_idx.to_i > first_idx.to_i end
matches_several_first?(line, rxp)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 740 def matches_several_first?(line, rxp) (line =~ prepared_regexp(rxp))&.zero? end
parse()
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 77 def parse @tree = [] @tree.extend(Hashie::Extensions::DeepLocate) @function_temp = [] @nesting = 0 @nesting_has_else = false @current_scope = [nil] @lnum = 0 # parse through lines to get the general structure (statements/flow control/functions/etc) out of it @lines.each_with_index do |line, lnum| @lnum = lnum parse_line(line) end func_calls = @tree.deep_locate(:passed_function_call) func_calls.each do |func| str = func[:passed_function_call] num = Integer(str.split('_').last) func[:passed_function_call] = parse_function_call(@function_temp[num]) end @tree end
parse_addition(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 652 def parse_addition(string) words = string.rpartition prepared_regexp(ADDITION_KEYWORDS) left = parse_argument(words.first.strip) right = parse_argument(words.last.strip) { addition: { left: left, right: right } } end
parse_and(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 479 def parse_and(string) words = string.rpartition prepared_regexp(AND_KEYWORDS) left = parse_argument(words.first.strip) right = parse_argument(words.last.strip) { and: { left: left, right: right } } end
parse_argument(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 417 def parse_argument(string) str = parse_literal_string(string) return str if str exp = parse_logic_operation(string) return exp if exp cmp = parse_comparison(string) return cmp if cmp math = parse_math_operations(string) return math if math fcl2 = pass_function_calls(string) return fcl2 if fcl2 fcl = parse_function_call(string) return fcl if fcl vals = parse_value_or_variable(string) return vals if vals end
parse_assignment(line)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 341 def parse_assignment(line) match_rxp = prepared_capture(ASSIGNMENT_FIRST_KEYWORDS, ASSIGNMENT_SECOND_KEYWORDS) right = parse_argument(line.match(match_rxp).captures.first.strip) left = parse_variables(line.match(match_rxp).captures.last.strip) left[:type] = :assignment { assignment: { left: left, right: right } } end
parse_break()
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 239 def parse_break { break: nil } end
parse_common_variable(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 606 def parse_common_variable(string) words = string.split(/\s/) words = words.map { |e| e.chars.select { |c| c =~ /[[:alpha:]]/ }.join } { variable_name: words.map(&:downcase).join('_') } end
parse_comparison(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 514 def parse_comparison(string) return false if string.strip.start_with?('"') && string.strip.strip.end_with?('"') && string.count('"') == 2 if string =~ prepared_regexp(GT_KEYWORDS) return parse_gt(string) elsif string =~ prepared_regexp(GTE_KEYWORDS) return parse_gte(string) elsif string =~ prepared_regexp(LT_KEYWORDS) return parse_lt(string) elsif string =~ prepared_regexp(LTE_KEYWORDS) return parse_lte(string) elsif string =~ prepared_regexp(INEQUALITY_KEYWORDS) return parse_inequality(string) elsif string =~ prepared_regexp(EQUALITY_KEYWORDS) return parse_equality(string) end false end
parse_continue()
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 243 def parse_continue { continue: nil } end
parse_decrement(line)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 214 def parse_decrement(line) match_rxp = prepared_capture(DECREMENT_FIRST_KEYWORDS, DECREMENT_SECOND_KEYWORDS) var = line.match(match_rxp).captures.first.strip capture = parse_variables(var) capture[:amount] = line.split(var).last.scan(/\bdown\b/i).count { decrement: capture } end
parse_division(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 676 def parse_division(string) words = string.rpartition prepared_regexp(DIVISION_KEYWORDS) left = parse_argument(words.first.strip) right = parse_argument(words.last.strip) { division: { left: left, right: right } } end
parse_else()
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 223 def parse_else if @nesting_has_else @nesting -= 1 @nesting_has_else = false add_to_tree parse_empty_line else @nesting_has_else = true end { else: nil } end
parse_empty_line()
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 235 def parse_empty_line { empty_line: nil } end
parse_equality(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 534 def parse_equality(string) words = string.rpartition prepared_regexp(EQUALITY_KEYWORDS) left = parse_argument(words.first.strip) right = parse_argument(words.last.strip) { equality: { left: left, right: right } } end
parse_function(line)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 392 def parse_function(line) words = line.split prepared_regexp(FUNCTION_KEYWORDS) funcname = parse_function_name(words.first.strip) argument = parse_function_definition_arguments(words.last.strip) { function: { name: funcname, argument: argument } } end
parse_function_call(line)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 269 def parse_function_call(line) words = line.split(/\s/) return false unless matches_any?(words, FUNCTION_CALL_KEYWORDS) words = line.split prepared_regexp(FUNCTION_CALL_KEYWORDS) left = parse_function_name(words.first.strip) right = parse_function_call_arguments(words.last.strip) { function_call: { left: left, right: right } } end
parse_function_call_arguments(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 259 def parse_function_call_arguments(string) words = string.split(Regexp.new(FUNCTION_CALL_SEPARATORS.join('|'))) arguments = [] words.each do |w| arguments << parse_value_or_variable(w.strip) end { argument_list: arguments } end
parse_function_definition_arguments(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 247 def parse_function_definition_arguments(string) words = string.split Regexp.new(FUNCTION_SEPARATORS.join('|')) arguments = [] words.each do |w| arg = parse_value_or_variable(w.strip) arg[:local_variable_name] = arg.delete(:variable_name) arguments << arg end { argument_list: arguments } end
parse_function_name(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 600 def parse_function_name(string) fname = parse_variables(string) fname[:function_name] = fname.delete(:variable_name) fname end
parse_gt(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 550 def parse_gt(string) words = string.rpartition prepared_regexp(GT_KEYWORDS) left = parse_argument(words.first.strip) right = parse_argument(words.last.strip) { gt: { left: left, right: right } } end
parse_gte(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 558 def parse_gte(string) words = string.rpartition prepared_regexp(GTE_KEYWORDS) left = parse_argument(words.first.strip) right = parse_argument(words.last.strip) { gte: { left: left, right: right } } end
parse_if(line)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 368 def parse_if(line) words = line.split prepared_regexp(IF_KEYWORDS) arg = consume_function_calls(words.last.strip) argument = parse_argument(arg) { if: { argument: argument } } end
parse_increment(line)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 205 def parse_increment(line) match_rxp = prepared_capture(INCREMENT_FIRST_KEYWORDS, INCREMENT_SECOND_KEYWORDS) var = line.match(match_rxp).captures.first.strip capture = parse_variables(var) capture[:amount] = line.split(var).last.scan(/\bup\b/i).count { increment: capture } end
parse_inequality(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 542 def parse_inequality(string) words = string.rpartition prepared_regexp(INEQUALITY_KEYWORDS) left = parse_argument(words.first.strip) right = parse_argument(words.last.strip) { inequality: { left: left, right: right } } end
parse_let_assignment(line)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 350 def parse_let_assignment(line) match_rxp = prepared_capture(LET_ASSIGNMENT_FIRST_KEYWORDS, LET_ASSIGNMENT_SECOND_KEYWORDS) right = parse_argument(line.match(match_rxp).captures.last.strip) left = parse_variables(line.match(match_rxp).captures.first.strip) left[:type] = :assignment # if the right is an expression and its variable name is empty # then it's a compound assignment which we translate back to an explicit one right.extend(Hashie::Extensions::DeepLocate) unless right.deep_locate(:variable_name).empty? if right.deep_locate(:variable_name).first[:variable_name].empty? right.deep_locate(:variable_name).first[:variable_name] = left[:variable_name] end end { assignment: { left: left, right: right } } end
parse_line(line)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 104 def parse_line(line) # consume comments and extra spaces line = line.gsub(/\(.*?\)/, '').strip if line.empty? if @nesting.positive? @current_scope.pop unless @current_scope[@nesting].nil? @nesting_has_else = false @nesting -= 1 end @current_scope.pop if @nesting.zero? add_to_tree(parse_empty_line) else obj = parse_line_content(line) add_to_tree obj update_nesting obj end end
parse_line_content(line)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 136 def parse_line_content(line) words = line.split(/\s/) if matches_first?(words, IF_KEYWORDS) return parse_if(line) elsif matches_first?(words, ELSE_KEYWORDS) return parse_else elsif matches_first?(words, WHILE_KEYWORDS) return parse_while(line) elsif matches_first?(words, UNTIL_KEYWORDS) return parse_until(line) elsif matches_separate?(words, ASSIGNMENT_FIRST_KEYWORDS, ASSIGNMENT_SECOND_KEYWORDS) return parse_assignment(line) elsif matches_separate?(words, LET_ASSIGNMENT_FIRST_KEYWORDS, LET_ASSIGNMENT_SECOND_KEYWORDS) return parse_let_assignment(line) elsif matches_several_first?(line, RETURN_KEYWORDS) return parse_return(line) elsif matches_first?(words, PRINT_KEYWORDS) return parse_print(line) else if matches_any?(words, POETIC_STRING_KEYWORDS) return parse_poetic_string(line) elsif matches_any?(words, POETIC_NUMBER_KEYWORDS) return parse_poetic_type_all(line) else return(parse_listen_to(line)) if matches_several_first?(line, LISTEN_TO_KEYWORDS) return(parse_listen) if matches_first?(words, LISTEN_KEYWORDS) return(parse_break) if matches_several_first?(line, BREAK_KEYWORDS) return(parse_continue) if matches_several_first?(line, CONTINUE_KEYWORDS) return(parse_function_call(line)) if matches_any?(words, FUNCTION_CALL_KEYWORDS) return parse_increment(line) if matches_separate?(words, INCREMENT_FIRST_KEYWORDS, INCREMENT_SECOND_KEYWORDS) return parse_decrement(line) if matches_separate?(words, DECREMENT_FIRST_KEYWORDS, DECREMENT_SECOND_KEYWORDS) return(parse_function(line)) if matches_any?(words, FUNCTION_KEYWORDS) end end raise KaiserRuby::RockstarSyntaxError, "couldn't parse line: #{line}:#{@lnum + 1}" end
parse_listen()
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 193 def parse_listen { listen: nil } end
parse_listen_to(line)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 185 def parse_listen_to(line) words = line.split prepared_regexp(LISTEN_TO_KEYWORDS) arg = parse_variables(words.last.strip) arg[:type] = :assignment { listen_to: arg } end
parse_literal_number(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 690 def parse_literal_number(string) num = Float(string) rescue string return false unless num.is_a?(Float) { number: num } end
parse_literal_string(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 684 def parse_literal_string(string) return false unless string.strip.start_with?('"') && string.strip.end_with?('"') && string.count('"') == 2 { string: string } end
parse_logic_operation(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 464 def parse_logic_operation(string) testable = string.partition(prepared_regexp(LOGIC_KEYWORDS)) return false if testable.first.count('"').odd? || testable.last.count('"').odd? if string =~ prepared_regexp(AND_KEYWORDS) return parse_and(string) elsif string =~ prepared_regexp(OR_KEYWORDS) return parse_or(string) elsif string =~ prepared_regexp(NOR_KEYWORDS) return parse_nor(string) end false end
parse_lt(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 566 def parse_lt(string) words = string.rpartition prepared_regexp(LT_KEYWORDS) left = parse_argument(words.first.strip) right = parse_argument(words.last.strip) { lt: { left: left, right: right } } end
parse_lte(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 574 def parse_lte(string) words = string.rpartition prepared_regexp(LTE_KEYWORDS) left = parse_argument(words.first.strip) right = parse_argument(words.last.strip) { lte: { left: left, right: right } } end
parse_math_operations(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 634 def parse_math_operations(string) return false if string.strip.start_with?('"') && string.strip.end_with?('"') && string.count('"') == 2 words = string.split(/\s/) if matches_any?(words, MULTIPLICATION_KEYWORDS) return parse_multiplication(string) elsif matches_any?(words, DIVISION_KEYWORDS) return parse_division(string) elsif matches_any?(words, ADDITION_KEYWORDS) return parse_addition(string) elsif matches_any?(words, SUBTRACTION_KEYWORDS) return parse_subtraction(string) end false end
parse_multiplication(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 668 def parse_multiplication(string) words = string.rpartition prepared_regexp(MULTIPLICATION_KEYWORDS) left = parse_argument(words.first.strip) right = parse_argument(words.last.strip) { multiplication: { left: left, right: right } } end
parse_nor(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 496 def parse_nor(string) words = string.rpartition prepared_regexp(NOR_KEYWORDS) left = parse_argument(words.first.strip) right = parse_argument(words.last.strip) { nor: { left: left, right: right } } end
parse_not(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 505 def parse_not(string) return false if string !~ /(?<!is )\bnot\b/i words = string.split prepared_regexp(NOT_KEYWORDS) argument = parse_argument(words.last.strip) { not: argument } end
parse_or(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 487 def parse_or(string) words = string.rpartition prepared_regexp(OR_KEYWORDS) left = parse_argument(words.first.strip) right = parse_argument(words.last.strip) { or: { left: left, right: right } } end
parse_poetic_number_value(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 457 def parse_poetic_number_value(string) num = parse_literal_number(string) return num if num { number_literal: string.strip } end
parse_poetic_string(line)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 280 def parse_poetic_string(line) words = line.partition prepared_regexp(POETIC_STRING_KEYWORDS) left = parse_variables(words.first.strip) right = { string: "\"#{words.last.strip}\"" } left[:type] = :assignment { poetic_string: { left: left, right: right } } end
parse_poetic_type_all(line)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 289 def parse_poetic_type_all(line) words = line.partition prepared_regexp(POETIC_NUMBER_KEYWORDS) left = parse_variables(words.first.strip) right = parse_type_value(words.last.strip) left[:type] = :assignment { poetic_type: { left: left, right: right } } end
parse_print(line)
click to toggle source
statements
# File lib/kaiser_ruby/parser.rb, line 177 def parse_print(line) words = line.partition prepared_regexp(PRINT_KEYWORDS) arg = consume_function_calls(words.last.strip) argument = parse_argument(arg) { print: argument } end
parse_pronoun()
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 626 def parse_pronoun { pronoun: nil } end
parse_proper_variable(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 613 def parse_proper_variable(string) words = string.split(/\s/) copied = words.dup copied.shift copied.each do |w| raise SyntaxError, "invalid proper variable name: #{string}:#{@lnum + 1}" unless w =~ /\A[[:upper:]]/ end words = words.map { |e| e.chars.select { |c| c =~ /[[:alpha:]]/ }.join } { variable_name: words.map(&:downcase).join('_') } end
parse_return(line)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 197 def parse_return(line) words = line.split prepared_regexp(RETURN_KEYWORDS) arg = consume_function_calls(words.last.strip) argument = parse_argument(arg) { return: argument } end
parse_subtraction(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 660 def parse_subtraction(string) words = string.rpartition prepared_regexp(SUBTRACTION_KEYWORDS) left = parse_argument(words.first.strip) right = parse_argument(words.last.strip) { subtraction: { left: left, right: right } } end
parse_type_literal(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 324 def parse_type_literal(string) words = string.split(/\s/) raise SyntaxError, "too many words in poetic type literal: #{string}:#{@lnum + 1}" if words.size > 1 if matches_first?(words, MYSTERIOUS_TYPE) { type: 'mysterious' } elsif matches_first?(words, NULL_TYPE) { type: 'null' } elsif matches_first?(words, TRUE_TYPE) { type: 'true' } elsif matches_first?(words, FALSE_TYPE) { type: 'false' } else raise SyntaxError, "unknown poetic type literal: #{string}:#{@lnum + 1}" end end
parse_type_value(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 298 def parse_type_value(string) words = string.split(/\s/) if matches_first?(words, MYSTERIOUS_TYPE) raise KaiserRuby::RockstarSyntaxError, "extra words are not allowed after literal type keyword: #{string}:#{@lnum + 1}" if words.count > 1 { type: 'mysterious' } elsif matches_first?(words, NULL_TYPE) raise KaiserRuby::RockstarSyntaxError, "extra words are not allowed after literal type keyword: #{string}:#{@lnum + 1}" if words.count > 1 { type: 'null' } elsif matches_first?(words, TRUE_TYPE) raise KaiserRuby::RockstarSyntaxError, "extra words are not allowed after literal type keyword: #{string}:#{@lnum + 1}" if words.count > 1 { type: 'true' } elsif matches_first?(words, FALSE_TYPE) raise KaiserRuby::RockstarSyntaxError, "extra words are not allowed after literal type keyword: #{string}:#{@lnum + 1}" if words.count > 1 { type: 'false' } elsif string.strip.start_with?('"') && string.strip.end_with?('"') parse_literal_string(string) else parse_poetic_number_value(string) end end
parse_until(line)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 376 def parse_until(line) words = line.split prepared_regexp(UNTIL_KEYWORDS) arg = consume_function_calls(words.last.strip) argument = parse_argument(arg) { until: { argument: argument } } end
parse_value_or_variable(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 440 def parse_value_or_variable(string) nt = parse_not(string) return nt if nt str = parse_literal_string(string) return str if str num = parse_literal_number(string) return num if num vars = parse_variables(string) return vars if vars tpl = parse_type_literal(string) return tpl if tpl end
parse_variables(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 582 def parse_variables(string) words = string.split(/\s/) words = words.map { |e| e.chars.select { |c| c =~ /[[:alnum:]]|\./ }.join } string = words.join(' ') if string =~ prepared_regexp(PRONOUN_KEYWORDS) return parse_pronoun elsif matches_first?(words, COMMON_VARIABLE_KEYWORDS) return parse_common_variable(string) elsif matches_all?(words, /\A[[:upper:]]/) && string !~ prepared_regexp(RESERVED_KEYWORDS) return parse_proper_variable(string) elsif words.count == 1 && string !~ prepared_regexp(RESERVED_KEYWORDS) return prase_simple_variable(string) end false end
parse_while(line)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 384 def parse_while(line) words = line.split prepared_regexp(WHILE_KEYWORDS) arg = consume_function_calls(words.last.strip) argument = parse_argument(arg) { while: { argument: argument } } end
pass_function_calls(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 411 def pass_function_calls(string) return false unless string.strip =~ /func_\d+\Z/ { passed_function_call: string } end
prase_simple_variable(string)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 630 def prase_simple_variable(string) { variable_name: string } end
prepared_capture(farr, sarr)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 713 def prepared_capture(farr, sarr) frxp = farr.map { |a| tokenize_word(a) }.join('|') srxp = sarr.map { |a| tokenize_word(a) }.join('|') Regexp.new(frxp + '(.*?)' + srxp + '(.*)', Regexp::IGNORECASE) end
prepared_regexp(array)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 708 def prepared_regexp(array) rxp = array.map { |a| tokenize_word(a) }.join('|') Regexp.new(rxp, Regexp::IGNORECASE) end
tokenize_word(word)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 751 def tokenize_word(word) return '\B' + Regexp.escape(word) + '\B' if MATH_TOKENS.include?(word) # apparently ' + ' is not a word so word boundaries don't work '\b' + word + '\b' end
update_nesting(object)
click to toggle source
# File lib/kaiser_ruby/parser.rb, line 125 def update_nesting(object) if %i[if function until while].include? object.keys.first @nesting += 1 @nesting_has_else = false end if object.keys.first == :function @current_scope.push object.deep_locate(:function_name).first.dig(:function_name) end end