class MetaCompiler_program

Public Class Methods

compile_file(inFile, out = nil) click to toggle source
# File bin/meta_compile, line 36
def self.compile_file(inFile, out = nil)
  outfh = (out == nil ? STDOUT : File.open(out, "w"))
  self.new.compile_string(File.read(inFile), outfh)
  outfh.close if out == nil
end

Public Instance Methods

compile_exp1() click to toggle source
# File bin/meta_compile, line 166
def compile_exp1
begin
@out.print 'begin'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
if true
compile_exp2     # Call the method for a rule
report_error() unless @match
begin
begin
scan '|'
if @match
@out.print 'break if @match'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
compile_exp2     # Call the method for a rule
report_error() unless @match
end
end while false  # This "while false" is needed since the break is not parsed correctly by Ruby otherwise
end while @match              # Loop while there is a match
@match = true                 # Since also zero matches is ok set flag here.
report_error() unless @match
@out.print 'end while false  # This "while false" is needed since the break is not parsed correctly by Ruby otherwise'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
end
end while false  # This "while false" is needed since the break is not parsed correctly by Ruby otherwise
end
compile_exp2() click to toggle source
# File bin/meta_compile, line 130
def compile_exp2
begin
begin
compile_exp3     # Call the method for a rule
if @match
@out.print 'if @match'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
end
break if @match
compile_out     # Call the method for a rule
if @match
@out.print 'if true'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
end
end while false  # This "while false" is needed since the break is not parsed correctly by Ruby otherwise
if @match
begin
begin
compile_exp3     # Call the method for a rule
if @match
@out.print 'report_error() unless @match'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
end
break if @match
compile_out     # Call the method for a rule
if @match
end
end while false  # This "while false" is needed since the break is not parsed correctly by Ruby otherwise
end while @match              # Loop while there is a match
@match = true                 # Since also zero matches is ok set flag here.
report_error() unless @match
@out.print 'end'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
end
end while false  # This "while false" is needed since the break is not parsed correctly by Ruby otherwise
end
compile_exp3() click to toggle source
# File bin/meta_compile, line 74
def compile_exp3
begin
scan /[A-Za-z]+[A-Za-z0-9_]+/
if @match
@out.print 'compile_'    # Print literal string on output stream
@out.print @match   # Print last matched token on output stream
@out.print '     # Call the method for a rule'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
end
break if @match
scan /\047[^\047]*\047/
if @match
@out.print 'scan '    # Print literal string on output stream
@out.print @match   # Print last matched token on output stream
@out.print "\n"     # Print newline on output stream
end
break if @match
scan '.id'
if @match
@out.print 'scan /[A-Za-z]+[A-Za-z0-9_]+/'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
end
break if @match
scan '.string'
if @match
@out.print 'scan /\047[^\047]*\047/'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
end
break if @match
scan '('
if @match
compile_exp1     # Call the method for a rule
report_error() unless @match
scan ')'
report_error() unless @match
end
break if @match
scan '.e'
if @match
@out.print '@match = true        # .e means empty so always matches => set flag.'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
end
break if @match
scan '*'
if @match
@out.print 'begin'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
compile_exp3     # Call the method for a rule
report_error() unless @match
@out.print 'end while @match              # Loop while there is a match'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '@match = true                 # Since also zero matches is ok set flag here.'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
end
end while false  # This "while false" is needed since the break is not parsed correctly by Ruby otherwise
end
compile_out() click to toggle source
# File bin/meta_compile, line 58
def compile_out
begin
scan '<'
if @match
begin
compile_outarg     # Call the method for a rule
end while @match              # Loop while there is a match
@match = true                 # Since also zero matches is ok set flag here.
report_error() unless @match
scan '>'
report_error() unless @match
@out.print '@out.print "\n"     # Print newline on output stream'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
end
end while false  # This "while false" is needed since the break is not parsed correctly by Ruby otherwise
end
compile_outarg() click to toggle source
# File bin/meta_compile, line 41
def compile_outarg
begin
scan '$'
if @match
@out.print '@out.print @match   # Print last matched token on output stream'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
end
break if @match
scan /\047[^\047]*\047/
if @match
@out.print '@out.print '    # Print literal string on output stream
@out.print @match   # Print last matched token on output stream
@out.print '    # Print literal string on output stream'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
end
end while false  # This "while false" is needed since the break is not parsed correctly by Ruby otherwise
end
compile_program() click to toggle source
# File bin/meta_compile, line 209
def compile_program
begin
scan '.syntax'
if @match
scan /[A-Za-z]+[A-Za-z0-9_]+/
report_error() unless @match
@out.print '#!/usr/bin/env ruby'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print 'require "strscan"'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print 'class StringScanner'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '  # Add scan for string since base StringScanner lack that...'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '  def scan_str(string)'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '    return nil unless self.peek(string.length) == string'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '    self.pos += string.length           # Advance the position in the input string'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '    return string'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '  end'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '  alias :old_scan :scan'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '  def scan(strOrRegexp)'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '    String === strOrRegexp ? scan_str(strOrRegexp) : old_scan(strOrRegexp)'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '  end'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print 'end'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print 'class MetaCompiler_'    # Print literal string on output stream
@out.print @match   # Print last matched token on output stream
@out.print "\n"     # Print newline on output stream
@out.print '  $compiler_class = self # Save class in global var for later reference below'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '  def compile_string(string, outFile)'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '    @in, @out = StringScanner.new(string), outFile'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '    compile_'    # Print literal string on output stream
@out.print @match   # Print last matched token on output stream
@out.print ' # call the main compile method to start compiling'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '  end'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '  # Scan for a string or regexp and update state based on match. Skips leading whitespace.'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '  def scan strOrRegexp'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '    @in.scan /\s*/   # Skip whitespace'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '    @match = @in.scan strOrRegexp'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '    # Since nil is same as false in Ruby we can set the flag to the matched token'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '    @last_matched_token = @match if @match # Update last matched only if a token was matched'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '  end'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '  def report_error'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '    pre_lines = @in.string[0, @in.pos].split("\n") # lines of input up to current position'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '    post_lines = @in.rest.split("\n")              # lines of input after current position'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '    message = "PARSE ERROR at line #{pre_lines.length}:\n  " + pre_lines.last.inspect + " @ "'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '    message += post_lines.first.inspect'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '    message += "\n  Last matched token: #{@last_matched_token}"'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '    raise message'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '  end'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '  def self.compile_file(inFile, out = nil)'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '    outfh = (out == nil ? STDOUT : File.open(out, "w"))'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '    self.new.compile_string(File.read(inFile), outfh)'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '    outfh.close if out == nil'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '  end'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
begin
compile_rule     # Call the method for a rule
end while @match              # Loop while there is a match
@match = true                 # Since also zero matches is ok set flag here.
report_error() unless @match
scan '.end'
report_error() unless @match
@out.print 'end'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print 'if ARGV.length < 1 || ARGV.length > 2'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '  puts "ERROR: wrong number of parameters\n\n"'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '  puts "Usage: #{File.basename($0)} <input_file> [output_file]"'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '  exit(-1)'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print 'else'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print '  $compiler_class.compile_file(ARGV[0], ARGV[1])'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
@out.print 'end'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
end
end while false  # This "while false" is needed since the break is not parsed correctly by Ruby otherwise
end
compile_rule() click to toggle source
# File bin/meta_compile, line 191
def compile_rule
begin
scan /[A-Za-z]+[A-Za-z0-9_]+/
if @match
@out.print 'def compile_'    # Print literal string on output stream
@out.print @match   # Print last matched token on output stream
@out.print "\n"     # Print newline on output stream
scan '='
report_error() unless @match
compile_exp1     # Call the method for a rule
report_error() unless @match
scan ';'
report_error() unless @match
@out.print 'end'    # Print literal string on output stream
@out.print "\n"     # Print newline on output stream
end
end while false  # This "while false" is needed since the break is not parsed correctly by Ruby otherwise
end
compile_string(string, outFile) click to toggle source
# File bin/meta_compile, line 17
def compile_string(string, outFile)
  @in, @out = StringScanner.new(string), outFile
  compile_program # call the main compile method to start compiling
end
report_error() click to toggle source
# File bin/meta_compile, line 28
def report_error
  pre_lines = @in.string[0, @in.pos].split("\n") # lines of input up to current position
  post_lines = @in.rest.split("\n")              # lines of input after current position
  message = "PARSE ERROR at line #{pre_lines.length}:\n  " + pre_lines.last.inspect + " @ "
  message += post_lines.first.inspect
  message += "\n  Last matched token: #{@last_matched_token}"
  raise message
end
scan(strOrRegexp) click to toggle source

Scan for a string or regexp and update state based on match. Skips leading whitespace.

# File bin/meta_compile, line 22
def scan strOrRegexp
  @in.scan /\s*/   # Skip whitespace
  @match = @in.scan strOrRegexp
  # Since nil is same as false in Ruby we can set the flag to the matched token
  @last_matched_token = @match if @match # Update last matched only if a token was matched
end