module Minjs::Lex::Statement

12

Public Instance Methods

block(var_env) click to toggle source

Tests next literals sequence is Block or not.

@see www.ecma-international.org/ecma-262 ECMA262 12.1

# File lib/minjs/lex/statement.rb, line 58
def block(var_env)
  pos0 = pos
  return nil unless eql_lit?(ECMA262::PUNC_LCURLYBRAC)
  if eql_lit?(ECMA262::PUNC_RCURLYBRAC)
    return ECMA262::StBlock.new(ECMA262::StatementList.new([]))
  end

  if s = statement_list(var_env) and eql_lit?(ECMA262::PUNC_RCURLYBRAC)
    ECMA262::StBlock.new(s)
  else
    raise ParseError.new('no "}" end of block', lex)
  end
end
break_statement(var_env) click to toggle source

Tests next literals sequence is BreakStatement or not.

@see www.ecma-international.org/ecma-262 ECMA262 12.8

# File lib/minjs/lex/statement.rb, line 319
def break_statement(var_env)
  return nil unless eql_lit?(ECMA262::ID_BREAK)

  if semicolon(var_env)
    ECMA262::StBreak.new
  elsif e=identifier(var_env) and semicolon(var_env)
    ECMA262::StBreak.new(e)
  else
    if e
      raise ParseError.new("no semicolon at end of break statement", self)
    else
      raise ParseError.new("unexpected token", self)
    end
  end
end
continue_statement(var_env) click to toggle source

Tests next literals sequence is ContinueStatement or not.

@see www.ecma-international.org/ecma-262 ECMA262 12.7

# File lib/minjs/lex/statement.rb, line 300
def continue_statement(var_env)
  return nil unless eql_lit?(ECMA262::ID_CONTINUE)

  if semicolon(var_env)
    ECMA262::StContinue.new
  elsif e=identifier(var_env) and semicolon(var_env)
    ECMA262::StContinue.new(e)
  else
    if e
      raise ParseError.new("no semicolon at end of continue statement", self)
    else
      raise ParseError.new("unexpected token", self)
    end
  end
end
debugger_statement(var_env) click to toggle source

Tests next literals sequence is DebuggerStatement or not.

@see www.ecma-international.org/ecma-262 ECMA262 12.15

# File lib/minjs/lex/statement.rb, line 479
def debugger_statement(var_env)
  return nil unless eql_lit?(ECMA262::ID_DEBUGGER)
  if semicolon(var_env)
    ECMA262::StDebugger.new
  else
    raise ParseError.new("no semicolon at end of debugger statement", self)
  end
end
empty_statement(var_env) click to toggle source

Tests next literals sequence is EmptyStatement or not.

@see www.ecma-international.org/ecma-262 ECMA262 12.3

# File lib/minjs/lex/statement.rb, line 152
def empty_statement(var_env)
  a = peek_lit(nil)
  if a == ECMA262::PUNC_SEMICOLON
    fwd_after_peek
    ECMA262::StEmpty.new
  else
    nil
  end
end
exp_statement(var_env) click to toggle source

Tests next literals sequence is ExpressionStatement or not.

@see www.ecma-international.org/ecma-262 ECMA262 12.4

# File lib/minjs/lex/statement.rb, line 164
def exp_statement(var_env)
  if (a = peek_lit(nil)).eql? ECMA262::PUNC_LCURLYBRAC
    return block(var_env)
  end
  if a.eql? ECMA262::ID_FUNCTION
    return func_declaration(var_env)
  end


  if a = exp(var_env, {})
    if semicolon(var_env)
      ECMA262::StExp.new(a)
    # There is a possibility of labelled statemet if
    # exp_statement call before labelled_statement
    else
      raise ParseError.new("no semicolon at end of expression statement", self)
    end
  else
    nil
  end
end
if_statement(var_env) click to toggle source

Tests next literals sequence is IfStatement or not.

@see www.ecma-international.org/ecma-262 ECMA262 12.5

# File lib/minjs/lex/statement.rb, line 188
def if_statement(var_env)
  return nil unless eql_lit?(ECMA262::ID_IF)
  unless(eql_lit?(ECMA262::PUNC_LPARENTHESIS) and cond=exp(var_env, {}) and
         eql_lit?(ECMA262::PUNC_RPARENTHESIS) and s = statement(var_env))
    raise ParseError.new("unexpected token", self)
  end
  if(eql_lit?(ECMA262::ID_ELSE) and e = statement(var_env))
    ECMA262::StIf.new(cond, s, e)
  else
    ECMA262::StIf.new(cond, s, nil)
  end
end
iteration_statement(var_env) click to toggle source

Tests next literals sequence is IterationStatement or not.

@see www.ecma-international.org/ecma-262 ECMA262 12.6

# File lib/minjs/lex/statement.rb, line 203
def iteration_statement(var_env)
  for_statement(var_env) or while_statement(var_env) or do_while_statement(var_env)
end
labelled_statement(var_env) click to toggle source

Tests next literals sequence is LabelledStatement or not.

@see www.ecma-international.org/ecma-262 ECMA262 12.12

# File lib/minjs/lex/statement.rb, line 402
def labelled_statement(var_env)
  eval_lit {
    if i=identifier(var_env) and s1=eql_lit?(ECMA262::PUNC_COLON)
      if s=statement(var_env)
        ECMA262::StLabelled.new(i, s)
      else
        raise ParseError.new("unexpected token", self)
      end
    else
      nil
    end
  }
end
return_statement(var_env) click to toggle source

Tests next literals sequence is ReturnStatement or not.

@see www.ecma-international.org/ecma-262 ECMA262 12.9

# File lib/minjs/lex/statement.rb, line 337
def return_statement(var_env)
  return nil unless eql_lit?(ECMA262::ID_RETURN)

  if semicolon(var_env)
    ECMA262::StReturn.new
  elsif e=exp(var_env, {}) and semicolon(var_env)
    ECMA262::StReturn.new(e)
  else
    raise ParseError.new("unexpected token", self)
  end
end
semicolon(var_env) click to toggle source

Tests next literal is ‘;’ or ‘}’ or LT

# File lib/minjs/lex/statement.rb, line 8
def semicolon(var_env)
  a = peek_lit_nolt(nil)
  # ; ?
  if a == ECMA262::PUNC_SEMICOLON
    fwd_after_peek
    a
  # } ?
  elsif a == ECMA262::PUNC_RCURLYBRAC
    a
  # line feed?
  elsif a == ECMA262::LIT_LINE_TERMINATOR
    fwd_after_peek
    a
  # end of program
  elsif a.nil?
    fwd_after_peek
    ECMA262::LIT_LINE_TERMINATOR
  # line terminator?
  elsif a.lt?
    fwd_after_peek
    a
  else
    nil
  end
end
statement(var_env) click to toggle source

Tests next literals sequence is Statement or not.

# File lib/minjs/lex/statement.rb, line 35
def statement(var_env)
  (
    block(var_env) or               #12.1
    var_statement(var_env) or       #12.2
    if_statement(var_env) or        #12.5
    iteration_statement(var_env) or #12.6
    continue_statement(var_env) or  #12.7
    break_statement(var_env) or     #12.8
    return_statement(var_env) or    #12.9
    with_statement(var_env) or      #12.10
    switch_statement(var_env) or    #12.11
    labelled_statement(var_env) or  #12.12
    throw_statement(var_env) or     #12.13
    try_statement(var_env) or       #12.14
    debugger_statement(var_env) or  #12.15
    func_declaration(var_env) or    #13 => func.rb
    exp_statement(var_env) or       #12.4
    empty_statement(var_env)        #12.3
  )
end
switch_statement(var_env) click to toggle source

Tests next literals sequence is SwitchStatement or not.

@see www.ecma-international.org/ecma-262 ECMA262 12.11

# File lib/minjs/lex/statement.rb, line 363
def switch_statement(var_env)
  return nil unless eql_lit?(ECMA262::ID_SWITCH)

  if eql_lit?(ECMA262::PUNC_LPARENTHESIS) and e=exp(var_env, {}) and eql_lit?(ECMA262::PUNC_RPARENTHESIS) and  c = case_block(var_env)
    ECMA262::StSwitch.new(e, c)
  else
    raise ParseError.new("unexpected token", self)
  end
end
throw_statement(var_env) click to toggle source

Tests next literals sequence is ThrowStatement or not.

@see www.ecma-international.org/ecma-262 ECMA262 12.13

# File lib/minjs/lex/statement.rb, line 418
def throw_statement(var_env)
  return nil unless eql_lit?(ECMA262::ID_THROW)

  if semicolon(var_env)
    raise ParseError.new("no line terminator here", self)
  elsif e=exp(var_env, {}) and semi = semicolon(var_env)
    ECMA262::StThrow.new(e)
  else
    if e
      raise ParseError.new("no semicolon at end of throw statement", self)
    else
      raise ParseError.new("unexpected token", self)
    end
  end
end
try_statement(var_env) click to toggle source

Tests next literals sequence is TryStatement or not.

@see www.ecma-international.org/ecma-262 ECMA262 12.14

# File lib/minjs/lex/statement.rb, line 436
def try_statement(var_env)
  return nil unless eql_lit?(ECMA262::ID_TRY)
  #
  # The catch argument var_env must be executable lexical environment.
  # See compress_var
  #
  t = block(var_env)
  return nil unless t

  c = try_catch(var_env)
  f = try_finally(var_env)
  ECMA262::StTry.new(var_env, t, c, f)
end
var_statement(var_env) click to toggle source

Tests next literals sequence is VariableStatement or not.

@see www.ecma-international.org/ecma-262 ECMA262 12.2

# File lib/minjs/lex/statement.rb, line 84
def var_statement(var_env)
  return nil unless eql_lit?(ECMA262::ID_VAR)

  if vl = var_decl_list(var_env, {}) and semicolon(var_env)
    #10.5
    vl.each do |v|
      dn = v[0]
      var_env.record.create_mutable_binding(dn, nil)
      var_env.record.set_mutable_binding(dn, :undefined, nil)
    end
    ECMA262::StVar.new(var_env, vl)
  else
    raise Minjs::ParseError.new("unexpected token", lex)
  end
end
with_statement(var_env) click to toggle source

Tests next literals sequence is WithStatement or not.

@see www.ecma-international.org/ecma-262 ECMA262 12.10

# File lib/minjs/lex/statement.rb, line 351
def with_statement(var_env)
  return nil unless eql_lit?(ECMA262::ID_WITH)

  if eql_lit?(ECMA262::PUNC_LPARENTHESIS) and e=exp(var_env, {}) and eql_lit?(ECMA262::PUNC_RPARENTHESIS) and s=statement(var_env)
    ECMA262::StWith.new(var_env, e, s)
  else
    raise ParseError.new("unexpected token", self)
  end
end

Private Instance Methods

case_block(var_env) click to toggle source
# File lib/minjs/lex/statement.rb, line 373
def case_block(var_env)
  return nil unless eql_lit?(ECMA262::PUNC_LCURLYBRAC)
  _case_block = []
  while true
    if eql_lit?(ECMA262::ID_CASE)
      if e = exp(var_env, {}) and eql_lit?(ECMA262::PUNC_COLON)
        sl = statement_list(var_env)
        _case_block.push [e, sl]
      else
        raise ParseError.new("unexpected token", self)
      end
    elsif eql_lit?(ECMA262::ID_DEFAULT)
      if eql_lit?(ECMA262::PUNC_COLON)
        sl = statement_list(var_env)
        _case_block.push [nil, sl]
      else
        raise ParseError.new("unexpected token", self)
      end
    elsif eql_lit?(ECMA262::PUNC_RCURLYBRAC)
      break
    end
  end
  _case_block
end
do_while_statement(var_env) click to toggle source
# File lib/minjs/lex/statement.rb, line 216
def do_while_statement(var_env)
  return nil unless eql_lit?(ECMA262::ID_DO)
  if s=statement(var_env) and eql_lit?(ECMA262::ID_WHILE) and eql_lit?(ECMA262::PUNC_LPARENTHESIS) and e=exp(var_env, {}) and eql_lit?(ECMA262::PUNC_RPARENTHESIS) and semicolon(var_env)
    ECMA262::StDoWhile.new(e, s)
  else
    raise ParseError.new("unexpected token", self)
  end
end
for_statement(var_env) click to toggle source

12.6

for ( ExpressionNoInopt ; Expressionopt ; Expressionopt ) Statement
for ( var VariableDeclarationListNoIn ; Expressionopt ; Expressionopt ) Statement
for ( LeftHandSideExpression in Expression ) Statement
for ( var VariableDeclarationNoIn in Expression ) Statement
# File lib/minjs/lex/statement.rb, line 232
def for_statement(var_env)
  return nil unless eql_lit?(ECMA262::ID_FOR)
  raise ParseError('unexpected token', self) unless eql_lit?(ECMA262::PUNC_LPARENTHESIS)
  eval_lit{
    # for(var i in a)
    if eql_lit?(ECMA262::ID_VAR)
      eval_lit{
        if v=var_decl(var_env, :no_in => true) and eql_lit?(ECMA262::ID_IN)
          if e=exp(var_env, {}) and eql_lit?(ECMA262::PUNC_RPARENTHESIS) and s = statement(var_env)
            #10.5
            var_env.record.create_mutable_binding(v[0], nil)
            var_env.record.set_mutable_binding(v[0], :undefined, nil)
            ECMA262::StForInVar.new(var_env, v, e, s)
          else
            raise ParseError.new("unexpected token", self)
          end
        end
      } or eval_lit {
        # for(var i ; cond ; exp)
        if vl=var_decl_list(var_env, :no_in =>true) and s1=eql_lit?(ECMA262::PUNC_SEMICOLON) and (e=exp(var_env, {})||true) and s2=eql_lit?(ECMA262::PUNC_SEMICOLON) and (e2=exp(var_env, {})||true) and eql_lit?(ECMA262::PUNC_RPARENTHESIS) and s=statement(var_env)
          e = nil if e == true
          e2 = nil if e2 == true
          #10.5
          vl.each do |v|
            dn = v[0]
            var_env.record.create_mutable_binding(dn, nil)
            var_env.record.set_mutable_binding(dn, :undefined, nil)
          end
          ECMA262::StForVar.new(var_env, vl, e, e2, s)
        else
          if !s1
            raise ParseError.new("no semicolon", self)
          elsif !s2
            raise ParseError.new("no semicolon", self)
          else
            raise ParseError.new("unexpected token", self)
          end
        end
      }
    else # => for(i in exp) / for(i ; cond; exp)
      eval_lit{
        # for(i in exp)
        if v=left_hand_side_exp(var_env) and eql_lit?(ECMA262::ID_IN)
          if e=exp(var_env, {}) and eql_lit?(ECMA262::PUNC_RPARENTHESIS) and s=statement(var_env)
            ECMA262::StForIn.new(v, e, s)
          else
            raise ParseError.new("unexpected token", self)
          end
        end
      } or eval_lit{
        # for(i ; cond; exp)
        if (v=exp(var_env, :no_in => true) || true) and s1=eql_lit?(ECMA262::PUNC_SEMICOLON) and (e=exp(var_env, {}) || true) and s2=eql_lit?(ECMA262::PUNC_SEMICOLON) and (e2=exp(var_env, {})||true) and eql_lit?(ECMA262::PUNC_RPARENTHESIS) and s=statement(var_env)
          v = nil if v == true
          e = nil if e == true
          e2 = nil if e2 == true
          ECMA262::StFor.new(v, e, e2, s)
        else
          raise ParseError.new("unexpected token", self)
        end
      }
    end
  }
end
initialiser(var_env, options) click to toggle source

12.2

Initialiser :

AssignmentExpression

# File lib/minjs/lex/statement.rb, line 137
def initialiser(var_env, options)
  if eql_lit?(ECMA262::PUNC_ASSIGN)
    if a = assignment_exp(var_env, options)
      return a
    else
      raise ParseError.new("unexpceted token", self);
    end
  end
  nil
end
statement_list(var_env) click to toggle source
# File lib/minjs/lex/statement.rb, line 72
def statement_list(var_env)
  t = []
  while !eof? and s = statement(var_env)
    t.push(s)
  end
  ECMA262::StatementList.new(t)
end
try_catch(var_env) click to toggle source

12.14

Catch : catch ( Identifier ) Block

return [identigier, block]

# File lib/minjs/lex/statement.rb, line 456
def try_catch(var_env)
  return nil unless eql_lit?(ECMA262::ID_CATCH)

  if eql_lit?(ECMA262::PUNC_LPARENTHESIS) and i=identifier(var_env) and eql_lit?(ECMA262::PUNC_RPARENTHESIS) and b=block(var_env)
    new_var_env = ECMA262::LexEnv.new(outer: var_env)
    ECMA262::StTryCatch.new(new_var_env, i, b)
  else
    raise ParseError.new("unexpected token", self)
  end
end
try_finally(var_env) click to toggle source
# File lib/minjs/lex/statement.rb, line 467
def try_finally(var_env)
  return nil unless eql_lit?(ECMA262::ID_FINALLY)
  b = block(var_env)
  raise ParseError.new("unexpected token", self) if b.nil?
  b
end
var_decl(var_env, options) click to toggle source

12.2

VariableDeclaration : Identifier Initialiser

return tuple of [name, initialiser]

# File lib/minjs/lex/statement.rb, line 122
def var_decl(var_env, options)
  a = identifier(var_env)
  if !a
    raise ParseError.new("bad identifier", lex);
  else
    b = initialiser(var_env, options)
    [a, b]
  end
end
var_decl_list(var_env, options) click to toggle source

12.2

VariableDeclarationList : VariableDeclaration VariableDeclarationList , VariableDeclaration

# File lib/minjs/lex/statement.rb, line 105
def var_decl_list(var_env, options)
  list = []
  list.push(var_decl(var_env, options))

  while eql_lit?(ECMA262::PUNC_COMMA) and b = var_decl(var_env, options)
    list.push(b)
  end
  list
end
while_statement(var_env) click to toggle source
# File lib/minjs/lex/statement.rb, line 207
def while_statement(var_env)
  return nil unless eql_lit?(ECMA262::ID_WHILE)
  if eql_lit?(ECMA262::PUNC_LPARENTHESIS) and e=exp(var_env, {}) and eql_lit?(ECMA262::PUNC_RPARENTHESIS) and s=statement(var_env)
    ECMA262::StWhile.new(e, s)
  else
    raise ParseError.new("unexpected token", self)
  end
end