Class: Gloo::Core::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/gloo/core/parser.rb

Instance Method Summary collapse

Constructor Details

#initialize(engine) ⇒ Parser

Set up the parser.



15
16
17
18
# File 'lib/gloo/core/parser.rb', line 15

def initialize( engine )
  @engine = engine
  @engine.log.debug 'parser intialized...'
end

Instance Method Details

#inline_call_opener?(cmd, paren_index) ⇒ Boolean

Is the '(' at the given index immediately preceded (no space) by an inline-call keyword, eg. invoke( or ~>( ? Shares its keyword list with Gloo::Core::Tokens, which is where such a call actually gets recognized as one token.

Returns:

  • (Boolean)


88
89
90
91
92
# File 'lib/gloo/core/parser.rb', line 88

def inline_call_opener?( cmd, paren_index )
  before = cmd[ 0...paren_index ]
  word = before[ /\S*\z/ ]
  return Gloo::Core::Tokens::CALL_OPENERS.include?( word )
end

#matching_open_paren_index(cmd) ⇒ Object

Find the index of the '(' that balances the command's final ')', counting depth from the end so an inline call earlier in the command (or nested parens) doesn't confuse the match. Returns nil if the command doesn't end with ')', or the parens aren't balanced.



67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/gloo/core/parser.rb', line 67

def matching_open_paren_index( cmd )
  return nil unless cmd.strip.end_with?( ')' )

  depth = 0
  ( cmd.length - 1 ).downto( 0 ) do |idx|
    case cmd[ idx ]
    when ')' then depth += 1
    when '('
      depth -= 1
      return idx if depth.zero?
    end
  end
  return nil
end

#parse_immediate(full_cmd) ⇒ Object

Parse a command from the immediate execution context.



23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/gloo/core/parser.rb', line 23

def parse_immediate( full_cmd )
  # Break the full command into verb and params
  cmd, params = split_params full_cmd

  # Params are the parenthetical part of the command at the end
  params = Gloo::Core::Tokens.new( params ) if params
  tokens = Gloo::Core::Tokens.new( cmd )
  dic = Gloo::Core::Dictionary.instance
  verb = dic.find_verb( tokens.verb )
  return verb.new( @engine, tokens, params ) if verb

  @engine.err "Verb '#{tokens.verb}' was not found."
  return nil
end

#run(cmd) ⇒ Object

Parse a command and then run it if it parsed correctly.



97
98
99
100
# File 'lib/gloo/core/parser.rb', line 97

def run( cmd )
  v = parse_immediate( cmd )
  Gloo::Exec::Runner.go( @engine, v ) if v
end

#split_params(cmd) ⇒ Object

If additional params were provided, split them out from the token list.

A trailing (...) is normally the optional-param convention (eg. show "text" (color)) and gets split off here. But a trailing (...) can also be an inline function call that happens to be the last thing in the command (eg. show invoke( functions.add 3 4 )) - that must be left alone so it flows into tokenizing as part of the main command.



49
50
51
52
53
54
55
56
57
58
# File 'lib/gloo/core/parser.rb', line 49

def split_params( cmd )
  i = matching_open_paren_index( cmd )
  return cmd, nil unless i
  return cmd, nil if inline_call_opener?( cmd, i )

  pstr = cmd[ i + 1..-1 ]
  params = pstr.strip[ 0..-2 ] if pstr
  cmd = cmd[ 0, i ].strip
  return cmd, params
end