Class: Parser
- Inherits:
-
Object
- Object
- Parser
- Defined in:
- lib/rdparse.rb
Defined Under Namespace
Classes: LexToken, ParseError
Instance Attribute Summary collapse
-
#logger ⇒ Object
readonly
Returns the value of attribute logger.
-
#pos ⇒ Object
Returns the value of attribute pos.
-
#rules ⇒ Object
readonly
Returns the value of attribute rules.
-
#string ⇒ Object
readonly
Returns the value of attribute string.
Instance Method Summary collapse
- #convert_regex_sensitive_token(token) ⇒ Object
-
#create_tokens_from_locale(locale) ⇒ Object
Recreate the tokenlist using the chosen locale file.
-
#expect(tok) ⇒ Object
Return the next token in the queue.
- #find_faulty_line ⇒ Object
- #find_surrounding_code(problem_pos) ⇒ Object
-
#initialize(language_name, debug_bool, locale, &block) ⇒ Parser
constructor
A new instance of Parser.
- #next_token ⇒ Object
- #parse(string) ⇒ Object
- #to_s ⇒ Object
-
#tokenize(string) ⇒ Object
Tokenize the string into small pieces.
- #translate_tokens_array(array) ⇒ Object
Constructor Details
#initialize(language_name, debug_bool, locale, &block) ⇒ Parser
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/rdparse.rb', line 128 def initialize(language_name, debug_bool, locale, &block) @debug_mode = debug_bool @logger = Logger.new(STDOUT) if @debug_mode @lex_tokens = [] @rules = {} @start = nil @language_name = language_name @file_string = '' create_tokens_from_locale(locale) false_value = @token_list['(false|true)'].split('|')[0]# Hacky solution to convoluted tokens true_value = @token_list['(false|true)'].split('|')[1] true_value = true_value[0..-2] false_value = false_value[1..] ScopeManager.new(true_value, false_value) # Hacky solution to convoluted tokens instance_eval(&block) end |
Instance Attribute Details
#logger ⇒ Object (readonly)
Returns the value of attribute logger.
123 124 125 |
# File 'lib/rdparse.rb', line 123 def logger @logger end |
#pos ⇒ Object
Returns the value of attribute pos.
122 123 124 |
# File 'lib/rdparse.rb', line 122 def pos @pos end |
#rules ⇒ Object (readonly)
Returns the value of attribute rules.
123 124 125 |
# File 'lib/rdparse.rb', line 123 def rules @rules end |
#string ⇒ Object (readonly)
Returns the value of attribute string.
123 124 125 |
# File 'lib/rdparse.rb', line 123 def string @string end |
Instance Method Details
#convert_regex_sensitive_token(token) ⇒ Object
190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/rdparse.rb', line 190 def convert_regex_sensitive_token(token) token = @token_list['end'] if token == :STOP # fulhack pga :END påstods inte funka för länge sen token = '[(]' if token == '(' token = '[)]' if token == ')' token = '[+]' if token == '+' token = '[-]' if token == '-' token = '[*]' if token == '*' token = '[/]' if token == '/' token = "#{@token_list['(not|!)'].split('|')[0][1..]}" if token == :NOT token = "#{@token_list['(and|&&)'].split('|')[0][1..]}" if token == :AND token = "#{@token_list['(or|\|\|)'].split('|')[0][1..]}" if token == :OR token end |
#create_tokens_from_locale(locale) ⇒ Object
Recreate the tokenlist using the chosen locale file
150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/rdparse.rb', line 150 def create_tokens_from_locale(locale) if locale == 'default' lang_file = File.read("#{LOCALES_PATH}/#{locale}") token_pairs = File.readlines("#{LOCALES_PATH}/#{lang_file}") else token_pairs = File.readlines("#{LOCALES_PATH}/#{locale}") end @token_list = Hash.new token_pairs.each do |pair| default_value, locale_value = pair.split(' ') @token_list[default_value] = locale_value end end |
#expect(tok) ⇒ Object
Return the next token in the queue
274 275 276 277 278 279 280 281 282 283 284 |
# File 'lib/rdparse.rb', line 274 def expect(tok) return tok if tok == :empty t = next_token if @pos - 1 > @max_pos @max_pos = @pos - 1 @expected = [] end return t if tok === t @expected << tok if @max_pos == @pos - 1 && !@expected.include?(tok) return nil end |
#find_faulty_line ⇒ Object
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
# File 'lib/rdparse.rb', line 224 def find_faulty_line tokens_before_problem = find_surrounding_code(@max_pos - 1) file_as_array_without_whitespaces = translate_tokens_array(tokens_before_problem) pattern = file_as_array_without_whitespaces.join('\s*') regex = Regexp.new(pattern) cleaned_string = @file_string.gsub(/;;.*/, '') match_data = regex.match(cleaned_string) num_lines = match_data[0].count("\n") + 1 problem = @tokens[@max_pos] problem = @token_list[problem.to_s.downcase] unless @token_list[problem.to_s.downcase].is_a?(NilClass) raise ParseError, "There is a problem around line #{num_lines}. Found <#{problem}>" end |
#find_surrounding_code(problem_pos) ⇒ Object
214 215 216 217 218 219 220 221 222 |
# File 'lib/rdparse.rb', line 214 def find_surrounding_code(problem_pos) tokens_before_problem = [] temp = problem_pos while temp >= 0 tokens_before_problem << @tokens[temp] temp -= 1 end tokens_before_problem.reverse end |
#next_token ⇒ Object
268 269 270 271 |
# File 'lib/rdparse.rb', line 268 def next_token @pos += 1 return @tokens[@pos - 1] end |
#parse(string) ⇒ Object
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 |
# File 'lib/rdparse.rb', line 242 def parse(string) # First, split the string according to the "token" instructions given. # Afterwards @tokens contains all tokens that are to be parsed. @file_string = string tokenize(string) # These variables are used to match if the total number of tokens # are consumed by the parser @pos = 0 @max_pos = 0 @expected = [] # Parse (and evaluate) the tokens received result = @start.parse # If there are unparsed extra tokens, signal error if @pos != @tokens.size if @tokens[@max_pos] == '(' || @tokens[@max_pos] == ')' raise ParseError, 'Mismatched parenthesis! In Emacs: M-x check-parens RET' end # raise ParseError, "Parse error. expected: '#{@expected.join(', ')}', found '#{@tokens[@max_pos]}'" return find_faulty_line end return result end |
#to_s ⇒ Object
286 287 288 |
# File 'lib/rdparse.rb', line 286 def to_s "Parser for #{@language_name}" end |
#tokenize(string) ⇒ Object
Tokenize the string into small pieces
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/rdparse.rb', line 165 def tokenize(string) @tokens = [] @string = string.clone until string.empty? # Unless any of the valid tokens of our language are the prefix of # 'string', we fail with an exception raise ParseError, "unable to lex '#{string}" unless @lex_tokens.any? do |tok| match = tok.pattern.match(string) # The regular expression of a token has matched the beginning of 'string' if match @logger.debug("Token #{match[0]} consumed as #{match[0]}") if @debug_mode # Also, evaluate this expression by using the block # associated with the token @tokens << tok.block.call(match.to_s) if tok.block # consume the match and proceed with the rest of the string string = match.post_match true else # this token pattern did not match, try the next false end # if end # raise end # until end |
#translate_tokens_array(array) ⇒ Object
204 205 206 207 208 209 210 211 212 |
# File 'lib/rdparse.rb', line 204 def translate_tokens_array(array) result = [] array.each do |token| token = convert_regex_sensitive_token(token) result << token unless token.is_a?(Symbol) result << @token_list[token.to_s.downcase] if token.is_a?(Symbol) end result end |