lib/interpreter/parse.tab.rb in nudge-0.1.2 vs lib/interpreter/parse.tab.rb in nudge-0.1.3

- old
+ new

@@ -1,12 +1,7 @@ # encoding: utf-8 -# DO NOT MODIFY!!!! -# This file is automatically generated by racc 1.4.5 -# from racc grammer file "parse.y". -# - require 'racc/parser' require 'strscan' class NudgeTree < Racc::Parser @@ -14,34 +9,54 @@ module_eval <<'..end parse.y modeval..ida1760a43d7', 'parse.y', 22 def self.from(string) nt = NudgeTree.new(string) result = nt.send(:do_parse) {tree:result, unused:nt.footnotes} + rescue ParseError => exc + {tree:NilPoint.new, unused:{}} end - attr_accessor :footnotes + attr_accessor :tree, :footnotes, :unused_footnotes + + def initialize(string) @tokens = [] @string = string.strip @footnotes = Hash.new { |hash, category| hash[category] = [] } - + @unused_footnotes = {} self.make_footnotes! self.tokenize! end + def make_footnotes! - return unless split_point = @string.index(/^«/) + return unless split_point = @string.index(/\n«/um) raise ParseError, "No program string" if split_point == 0 - ss = StringScanner.new(@string.slice!((split_point - 1)..-1)) + ss = StringScanner.new(@string.slice!((split_point)..-1)) - while ss.scan(/\n/) - @footnotes[ss.scan(/«[\p{Alpha}][_\p{Alnum}]*»/u)[1..-2]] << ss.scan(/[^\n]*/).strip # <-- /\n«/ + fn_head = /\n«([\p{Alpha}][_\p{Alnum}]*)»/u + + while ss.exist?(fn_head) + ss.scan_until(fn_head) + cat = ss[1] + if ss.exist?(/\n«/um) + ss.scan_until(/(.*?)\n«/um) + fn = ss[1] + elsif ss.eos? + fn = "" + else + ss.scan_until(/(.*)$/um) + fn = ss[1] + end + ss.pos -= 3 + @footnotes[cat] << fn.strip end end + def pop_footnote(category) value = @footnotes[category].shift if category == "code" embedded_footnotes = [""] @@ -50,55 +65,58 @@ end return value end + def collect_embedded_footnotes!(code_text, embedded_footnotes) - ss = StringScanner.new(code_text) - - while ss.skip_until(/«[\p{Alpha}][\p{Alnum}_]*»/) - category = ss.matched[1...-1] - footnote = @footnotes[category].shift + ss = StringScanner.new(code_text) + while ss.skip_until(/«([\p{Alpha}][\p{Alnum}_]*?)»/um) + category = ss[1] + footnote = @footnotes[category].shift || "" - embedded_footnotes << "«#{category}»#{footnote}" + embedded_footnotes << "«#{category}» #{footnote}" if category == "code" self.collect_embedded_footnotes!(footnote, embedded_footnotes) end end end + def next_token return @tokens.shift end + def tokenize! ss = StringScanner.new(@string) until ss.eos? @tokens << case c = ss.getch when /\s/ nil when /[{}«»]/ [c, 0] - when /[\p{Alpha}]/ - ss.pointer -= 1 - ss.scan(/[\p{Alpha}][\p{Alnum}_]*/) # <- \p{Alpha} + when /[\p{Alpha}]/u + ss.unscan + ss.scan(/[\p{Alpha}][_\p{Alnum}]*/u) # <- \p{Alpha} case m = ss.matched when "block", "ref", "do", "value" [m, 0] else [:ID, m] end else - raise ParseError, "Couldn't tokenize program string" + raise ParseError, "Couldn't tokenize program string \"#{@string}\"" end end @tokens.compact! @tokens << [false, false] end + def on_error(error_token_id, error_value, value_stack) raise ParseError, "Couldn't parse program string" end \ No newline at end of file