class XfOOrth::Parser

Attributes

source[R]

The source of the text to be parsed.

Public Class Methods

new(source) click to toggle source

Initialize this parser.
Parameters

  • source - The source of the text to be parsed.

# File lib/fOOrth/compiler/parser.rb, line 20
def initialize(source)
  @source = source
end

Public Instance Methods

get_string() click to toggle source

Get the balance of a string from the source code source.

# File lib/fOOrth/compiler/parser/get_string.rb, line 10
def get_string
  vm = Thread.current[:vm]
  vm.quotes, done, result = 1, false, ''

  begin
    next_char = @source.get

    if next_char == "\\"
      break if process_backslash(result)
    elsif next_char == '"' || @source.eoln?
      vm.quotes, done = 0, true
    elsif next_char >= ' '
      result << next_char
    end
  end until done

  result
end
get_word() click to toggle source

Get the next forth word from the source code source. This method recognizes and skips over comments in the source code.
Returns:

  • A string with the next non-comment language element or nil if none could be found.

# File lib/fOOrth/compiler/parser/normal.rb, line 14
def get_word
  loop do
    return nil unless (word = get_word_raw)

    if word == '('
      skip_over_comment
    elsif word == '//'
      skip_to_eoln
    else
      return word
    end
  end
end
get_word_or_string() click to toggle source

Get the next forth word and any embedded string data. This is used to support the quoted compiler mode.
Returns:

  • A string with the next non-comment language element or nil if none could be found.


Endemic Code Smells

  • :reek:TooManyStatements

# File lib/fOOrth/compiler/parser/special.rb, line 16
def get_word_or_string
  return nil unless (word = get_word)

  if word[-1] == '"'
    vm = Thread.current[:vm]
    vm.quotes, skip, done = 1, false, false

    until done
      return nil unless (next_char = @source.get)
      word << next_char

      if skip
        skip = false
      elsif next_char == '"'
        vm.quotes, done = 0, true
      else
        skip = (next_char == '\\')
      end
    end
  end

  word
end
get_word_raw() click to toggle source

Get the next forth word from the source code source. Recognizes, but does not process comments in the source code.
Returns:

  • A string with the next language element or nil if none could be found.

# File lib/fOOrth/compiler/parser/normal.rb, line 32
def get_word_raw
  #Skip white space.
  return nil unless (next_char = skip_white_space)

  #Gather the word token.
  word = ''

  begin
    word << next_char

    #Check for the three special cases.
    break if ['(', '//'].include?(word) || (next_char == '"')

    next_char = @source.get
  end while next_char && next_char > ' '

  word
end
process_16_bit() click to toggle source

Process a 16 bit hex character constant.

# File lib/fOOrth/compiler/parser/get_string.rb, line 59
def process_16_bit
  hex = process_hex_character + process_hex_character +
        process_hex_character + process_hex_character
  eval("\"\\u#{hex}\"")
end
process_8_bit() click to toggle source

Process an 8 bit hex character constant.

# File lib/fOOrth/compiler/parser/get_string.rb, line 53
def process_8_bit
  hex = process_hex_character + process_hex_character
  eval("\"\\x#{hex}\"")
end
process_backslash(buffer) click to toggle source

Process a backlash character found with a string in the source text.
Endemic Code Smells

  • :reek:TooManyStatements

# File lib/fOOrth/compiler/parser/get_string.rb, line 32
def process_backslash(buffer)
  next_char = @source.get

  if next_char == ' ' && @source.eoln?
    next_char = skip_white_space_or_to_eoln
    return true if ['"', ' '].include?(next_char)
  elsif next_char == 'n'
    next_char = "\n"
  elsif next_char == 'x'
    next_char = process_8_bit
  elsif next_char == 'u'
    next_char = process_16_bit
  elsif next_char != "\\" && next_char != '"'
    error "F10: Invalid string literal value: '\\#{next_char}'"
  end

  buffer << next_char
  false
end
process_hex_character() click to toggle source

Get a hex character from the input stream.

# File lib/fOOrth/compiler/parser/get_string.rb, line 66
def process_hex_character
  next_char = @source.get
  error "F10: Invalid hex character: '#{next_char}'" unless /\h/ =~ next_char

  next_char
end
skip_over_comment() click to toggle source

Skip over a portion of the source text until a ')' detected.
Returns:

  • true


Note:

  • Raises an XfOOrthError exception on an unterminated comment.


Endemic Code Smells

  • :reek:DuplicateMethodCall – false positive

# File lib/fOOrth/compiler/parser/skip.rb, line 35
def skip_over_comment
  vm = Thread.current[:vm]
  vm.parens += 1

  until @source.eof?
    input = @source.get

    if input == ')'
      vm.parens -= 1
      return true
    elsif input == '('
      skip_over_comment
    end
  end

  error "F10: Unbalanced comment detected."
end
skip_to_eoln() click to toggle source

Skip over a portion of the source text until end of line detected.
Returns:

  • true

# File lib/fOOrth/compiler/parser/skip.rb, line 23
def skip_to_eoln
  @source.get until @source.eoln?
  true
end
skip_white_space() click to toggle source

Skip over any white space.
Returns:

  • The first non-white space character or nil if none were found.

# File lib/fOOrth/compiler/parser/skip.rb, line 12
def skip_white_space
  begin
    return nil unless (next_char = @source.get)
  end while next_char <= ' '

  next_char
end
skip_white_space_or_to_eoln() click to toggle source

Skip till a non-white space or an end of line

# File lib/fOOrth/compiler/parser/skip.rb, line 54
def skip_white_space_or_to_eoln
  while (next_char = @source.get)
    return next_char if (next_char > ' ') || @source.eoln?
  end
end