Created
March 10, 2009 21:13
-
-
Save jolts/77138 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require File.dirname(__FILE__) + '/../lib/rules' | |
class ParseError < RuntimeError; end | |
module Parser | |
extend self | |
def is_valid_rule?(str) | |
$valid_rules.each do |key, regex| | |
return true if str.match(regex) | |
end | |
raise ParseError, "'#{str}' unable to parse line: '#{@pos}'" | |
false | |
end | |
def is_terminated?(str) | |
str.match(/^end$\z/) ? true : false | |
end | |
def match_rule(str) | |
$valid_rules.each { |key, regex| return key if str.match(regex) } | |
false | |
end | |
def is_valid_args?(str) | |
unless lambda { | |
str.match(/(\d+\,)+\d+/) | |
str.match(/\w+\(\w+\)/) | |
str.match(/\(\)$/) } | |
raise ParseError, "'#{str}' is not a valid method call, unable to parse line: '#{@pos}'" | |
end | |
end | |
def is_block? (str, rule) | |
if rule == :if_stmt or rule == :for_stmt or str.match(/end$/) or str.match(/do$/) | |
true | |
end | |
end | |
def parse_list(str) | |
tokens = [/^list../, //] | |
line = str.clone | |
end | |
def get_endposition | |
# Returns an integer with index of the most outer end and put it in a | |
# instance variable | |
str = Array.new @string | |
until str.empty? | |
index = str.index("end") | |
str.shift | |
end | |
0 unless index | |
end | |
def parse_block(str, rule) | |
block_tokens = {:in => /in/, | |
:operator => /(==|=|!=|<=|>=)/, | |
:left_token => /if|foreach\s+(\w+)\s+/, | |
:right_token => /if|foreach\s+\w+\s+\w+\s+(.+)/, | |
:end => /end/ | |
} | |
rule = match_rule str | |
current_rule = {rule => []} | |
until @pos == @end_pos | |
block_tokens.each do |key, regex| | |
if str.match(regex) | |
if key == :operator | |
current_rule[rule] << str[regex] | |
elsif rule == :left_token | |
current_rule[rule].insert(0, str[regex]) | |
elsif rule == :right_token | |
current_rule[rule] << str[regex] | |
else | |
current_rule[rule] << {key => str[regex].strip} | |
end | |
end | |
@pos = @end_pos | |
end | |
end | |
current_rule | |
end | |
def tokenize_rule(str, hash=nil) | |
rule = match_rule @current_row | |
hash = {rule => []} unless hash | |
tokens = {:operator => /(==|=|!=|<=|>=)/, | |
:internal_var => /^\$.+/, | |
:variable => /(^\w+)/, | |
:num => /\s+(\d+)/, | |
:string => /(("|')(.+)("|'))/, | |
:end => /end/} | |
tokens.each do |key, regex| | |
if str.match(regex) | |
if key == :operator | |
hash[rule] << str[regex] | |
else | |
if key == :variable and hash[rule][0] == ["print"] then; next; end | |
hash[rule] << {key => str[regex]} | |
end | |
end | |
end | |
hash | |
end | |
def parse_func_call(str) | |
current_rule = {:func_call => []} | |
current_rule[:func_call] << str[/^(\w+\.\w+|\w+)/].split(/\./) | |
current_rule = tokenize_rule str, current_rule | |
current_rule | |
end | |
def tokenize(str, rule) | |
if str.match(/do$/) | |
current_rule = parse_block str, rule | |
elsif rule == :func_call | |
current_rule = parse_func_call str | |
elsif is_valid_rule? str | |
current_rule = tokenize_rule str | |
elsif rule == :list | |
current_rule = parse_list str, rule | |
end | |
current_rule | |
end | |
def parse(str) | |
result = [] | |
@string = str.clone.strip.split(/\n/) # We work on a copy of the string to parse | |
@string.each do |row| | |
rule = match_rule(row) | |
@pos = @string.index(row) | |
@end_pos = get_endposition if is_block? row, rule | |
@current_row = row | |
if rule | |
puts rule | |
current_rule = tokenize row, rule | |
is_valid_args? row if rule == :func_call | |
result << current_rule | |
# Is ment to parse things lower down the parse-tree, like | |
# expressions, variables assignments etc first, and then | |
# gsub them out of stringing | |
# Split string depending on rule and and put in an hash | |
end | |
end | |
# Returns an array, where each element is a hash with key as a rule and | |
# string to evaluate by evaluator | |
result | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment