lib/minjs/expression.rb in minjs-0.2.2 vs lib/minjs/expression.rb in minjs-0.3.0
- old
+ new
@@ -1,732 +1,833 @@
+# coding: utf-8
module Minjs
module Exp
#
# Primary Expressions
# 11.1
#
def primary_exp(lex, context, options)
@logger.debug "*** primary_exp"
- if lex.match_lit(ECMA262::ID_THIS)
- @logger.debug "*** primary_exp => this"
- return ECMA262::ID_THIS
+ if lex.eql_lit?(ECMA262::ID_THIS)
+ @logger.debug "*** primary_exp => this"
+ return ECMA262::This.new(context)
end
# (exp)
- if lex.match_lit(ECMA262::PUNC_LPARENTHESIS)
- if a=exp(lex, context, options) and lex.match_lit(ECMA262::PUNC_RPARENTHESIS)
+ if lex.eql_lit?(ECMA262::PUNC_LPARENTHESIS)
+ if a=exp(lex, context, options) and lex.eql_lit?(ECMA262::PUNC_RPARENTHESIS)
@logger.debug "*** primary_exp => ()"
return ECMA262::ExpParen.new(a)
else
raise ParseError.new("no `)' at end of expression", lex)
end
end
- # identifier || literal || array_literal || object_literal
- t = lex.eval_lit {
- identifier(lex, context)
- } || lex.eval_lit {
- literal(lex, context)
- } || lex.eval_lit {
- array_literal(lex, context, options)
- } || lex.eval_lit {
- object_literal(lex, context, options)
- }
+ t = identifier(lex, context) ||
+ literal(lex, context) ||
+ array_literal(lex, context, options) ||
+ object_literal(lex, context, options)
+
@logger.debug {
"*** primary_exp => #{t ? t.to_js : t}"
}
t
end
+ # 7.8
+ # 7.8.1
+ # 7.8.2
#
+ # Literal ::
+ # NullLiteral
+ # BooleanLiteral
+ # NumericLiteral
+ # StringLiteral
+ # RegularExpressionLiteral
+ #
+ def literal(lex, context)
+ a = lex.peek_lit(:regexp)
+ if a.kind_of? ECMA262::ECMA262Numeric or a.kind_of? ECMA262::ECMA262String or a.kind_of? ECMA262::ECMA262RegExp
+ lex.fwd_after_peek
+ a
+ elsif a.eql? ECMA262::ID_NULL
+ lex.fwd_after_peek
+ ECMA262::Null.get
+ elsif a.eql? ECMA262::ID_TRUE
+ lex.fwd_after_peek
+ ECMA262::Boolean.get(:true)
+ elsif a.eql? ECMA262::ID_FALSE
+ lex.fwd_after_peek
+ ECMA262::Boolean.get(:false)
+ else
+ nil
+ end
+ end
+
+ #
# 11.1.2
#
def identifier(lex, context)
- lex.eval_lit {
- if (a = lex.fwd_lit).kind_of? ECMA262::IdentifierName and !a.reserved?
- a.context = context
- a
- else
- nil
- end
- }
+ a = lex.peek_lit(:regexp)
+ if a.kind_of? ECMA262::IdentifierName and !a.reserved?
+ lex.fwd_after_peek
+ a.context = context
+ a
+ else
+ nil
+ end
end
-
#
# 11.1.4
#
def array_literal(lex, context, options)
- return nil unless lex.match_lit(ECMA262::PUNC_LSQBRAC)
+ return nil unless lex.eql_lit?(ECMA262::PUNC_LSQBRAC)
t = []
- lex.eval_lit {
- while true
- if lex.match_lit(ECMA262::PUNC_COMMA)
- t.push(nil)
- elsif lex.match_lit(ECMA262::PUNC_RSQBRAC)
- break
- elsif a = assignment_exp(lex, context, {})
- t.push(a)
- lex.match_lit(ECMA262::PUNC_COMMA)
- else
- raise ParseError.new("no `]' end of array", lex)
- end
+ while true
+ if lex.eql_lit?(ECMA262::PUNC_COMMA)
+ t.push(nil)
+ elsif lex.eql_lit?(ECMA262::PUNC_RSQBRAC)
+ break
+ elsif a = assignment_exp(lex, context, {})
+ t.push(a)
+ lex.eql_lit?(ECMA262::PUNC_COMMA)
+ else
+ raise ParseError.new("no `]' end of array", lex)
end
- ECMA262::ECMA262Array.new(t)
- }
+ end
+ ECMA262::ECMA262Array.new(t)
end
#
# 11.1.5
#
+ # ObjectLiteral :
+ # { }
+ # { PropertyNameAndValueList }
+ # { PropertyNameAndValueList , }
+ #
def object_literal(lex, context, options)
- return nil unless lex.match_lit(ECMA262::PUNC_LCURLYBRAC)
- lex.eval_lit {
- if lex.match_lit(ECMA262::PUNC_RCURLYBRAC)
- next ECMA262::ECMA262Object.new([])
- end
- if h=property_name_and_value_list(lex, context, options)
- ECMA262::ECMA262Object.new(h)
- else
- raise ParseError.new("no `}' end of object", lex)
- end
- }
+ return nil unless lex.eql_lit?(ECMA262::PUNC_LCURLYBRAC)
+ #{}
+ if lex.eql_lit?(ECMA262::PUNC_RCURLYBRAC)
+ ECMA262::ECMA262Object.new([])
+ else
+ ECMA262::ECMA262Object.new(property_name_and_value_list(lex, context, options))
+ end
end
+ # 11.1.5
#
+ # PropertyNameAndValueList :
+ # PropertyAssignment
+ # PropertyNameAndValueList , PropertyAssignment
+ #
+ # PropertyAssignment :
+ # PropertyName : AssignmentExpression
+ # get PropertyName ( ) { FunctionBody }
+ # set PropertyName ( PropertySetParameterList ) { FunctionBody }
+ #
+ #
# name: exp
# get name(){funcbody}
# set name(args){funcbody}
#
def property_name_and_value_list(lex, context, options)
- lex.eval_lit{
- h = []
- while !lex.eof?
- if lex.match_lit(ECMA262::PUNC_RCURLYBRAC)
- break
- end
- lex.eval_lit{
- if lex.match_lit(ECMA262::ID_GET) and a=property_name(lex, context) and lex.match_lit(ECMA262::PUNC_LPARENTHESIS) and lex.match_lit(ECMA262::PUNC_RPARENTHESIS) and lex.match_lit(ECMA262::PUNC_LCURLYBRAC) and b=func_body(lex, context) and lex.match_lit(ECMA262::PUNC_RCURLYBRAC)
- h.push([a, ECMA262::StFunc.new(context, ECMA262::ID_GET, [], b, :getter => true)])
- elsif lex.match_lit(ECMA262::ID_SET) and a=property_name(lex, context) and lex.match_lit(ECMA262::PUNC_LPARENTHESIS) and arg=property_set_parameter_list(lex, context) and lex.match_lit(ECMA262::PUNC_RPARENTHESIS) and lex.match_lit(ECMA262::PUNC_LCURLYBRAC) and b=func_body(lex, context) and lex.match_lit(ECMA262::PUNC_RCURLYBRAC)
- h.push([a, ECMA262::StFunc.new(context, ECMA262::ID_SET, arg, b, :setter => true)])
+ h = []
+ while !lex.eof?
+ #get
+ if lex.match_lit? ECMA262::ID_GET
+ # {get : val}
+ if lex.eql_lit? ECMA262::PUNC_COLON
+ b = assignment_exp(lex, context, options)
+ h.push([ECMA262::ID_GET, b])
+ # {get name(){}}
+ else
+ new_context = ECMA262::Context.new
+ new_context.lex_env = context.lex_env.new_declarative_env()
+ new_context.var_env = context.var_env.new_declarative_env()
+ if(a = property_name(lex, context) and
+ lex.eql_lit? ECMA262::PUNC_LPARENTHESIS and
+ lex.eql_lit? ECMA262::PUNC_RPARENTHESIS and
+ lex.eql_lit? ECMA262::PUNC_LCURLYBRAC and
+ b = func_body(lex, new_context) and
+ lex.eql_lit? ECMA262::PUNC_RCURLYBRAC)
+ h.push([a, ECMA262::StFunc.new(new_context, ECMA262::ID_GET, [], b, :getter => true)])
else
- nil
+ raise ParseError.new("unexpceted token", lex)
end
- } or lex.eval_lit{
- a=property_name(lex, context) and lex.match_lit(ECMA262::PUNC_COLON) and b=assignment_exp(lex, context, options)
- h.push([a, b])
- }
-
- if lex.match_lit(ECMA262::PUNC_COMMA)
- break if lex.match_lit(ECMA262::PUNC_RCURLYBRAC)
- elsif lex.match_lit(ECMA262::PUNC_RCURLYBRAC)
- break
+ end
+ #set
+ elsif lex.match_lit?(ECMA262::ID_SET)
+ # {set : val}
+ if lex.eql_lit? ECMA262::PUNC_COLON
+ b = assignment_exp(lex, context, options)
+ h.push([ECMA262::ID_SET, b])
+ # {set name(arg){}}
else
- raise ParseError.new("no `}' end of object", lex)
+ new_context = ECMA262::Context.new
+ new_context.lex_env = context.lex_env.new_declarative_env()
+ new_context.var_env = context.var_env.new_declarative_env()
+ if(a = property_name(lex, context) and
+ lex.eql_lit? ECMA262::PUNC_LPARENTHESIS and
+ arg = property_set_parameter_list(lex, new_context) and
+ lex.eql_lit? ECMA262::PUNC_RPARENTHESIS and
+ lex.eql_lit? ECMA262::PUNC_LCURLYBRAC and
+ b = func_body(lex, new_context) and
+ lex.eql_lit? ECMA262::PUNC_RCURLYBRAC)
+ h.push([a, ECMA262::StFunc.new(new_context, ECMA262::ID_SET, arg, b, :setter => true)])
+ else
+ raise ParseError.new("unexpceted token", lex)
+ end
end
+ #property
+ elsif(a = property_name(lex, context) and
+ lex.eql_lit? ECMA262::PUNC_COLON and
+ b = assignment_exp(lex, context, options))
+ h.push([a, b])
+ else
+ raise ParseError.new("unexpceted token", lex)
end
- h
- }
- end
- def property_name(lex, context)
- lex.eval_lit {
- a = lex.fwd_lit
- if a.kind_of?(ECMA262::ECMA262String)
- a
- elsif a.kind_of?(ECMA262::IdentifierName)
- ECMA262::ECMA262String.new(a.to_js)
- elsif a.kind_of?(ECMA262::ECMA262Numeric)
- a
+ if lex.eql_lit?(ECMA262::PUNC_COMMA)
+ break if lex.eql_lit?(ECMA262::PUNC_RCURLYBRAC)
+ elsif lex.eql_lit?(ECMA262::PUNC_RCURLYBRAC)
+ break
else
- nil
+ raise ParseError.new("no `}' end of object", lex)
end
- }
+ end
+ h
end
- def property_set_parameter_list(lex, context)
- lex.eval_lit {
- a = lex.fwd_lit
- if a.kind_of?(ECMA262::IdentifierName) and !a.reserved?
- [a]
- else
- nil
- end
- }
+ # 11.1.5
+ #
+ # PropertyName :
+ # IdentifierName
+ # StringLiteral
+ # NumericLiteral
+ #
+ def property_name(lex, context)
+ a = lex.fwd_lit(nil)
+ if a.kind_of?(ECMA262::ECMA262String)
+ a
+ elsif a.kind_of?(ECMA262::IdentifierName)
+ ECMA262::ECMA262String.new(a.to_js)
+ elsif a.kind_of?(ECMA262::ECMA262Numeric)
+ a
+ elsif a.eql?(ECMA262::PUNC_COLON)
+ nil
+ else
+ raise ParseError.new("unexpceted token", lex)
+ end
end
+ # 11.1.5
#
+ # PropertySetParameterList :
+ # Identifier
+ #
+ def property_set_parameter_list(lex, context)
+ argName = identifier(lex, context)
+ context.var_env.record.create_mutable_binding(argName, nil)
+ context.var_env.record.set_mutable_binding(argName, :undefined, nil, {:_parameter_list => true})
+ context.lex_env.record.create_mutable_binding(argName, nil)
+ context.lex_env.record.set_mutable_binding(argName, :undefined, nil, {:_parameter_list => true})
+ [argName]
+ end
+
# 11.2
#
+ # LeftHandSideExpression :
+ # NewExpression
+ # CallExpression
+ #
def left_hand_side_exp(lex, context, options)
@logger.debug "*** left_hand_side_exp"
- t = lex.eval_lit{
- call_exp(lex, context, options)
- } || lex.eval_lit{
- new_exp(lex, context, options)
- }
+ t = call_exp(lex, context, options) || new_exp(lex, context, options)
+ #t = new_exp(lex, context, options) || call_exp(lex, context, options)
+
@logger.debug{
"*** left_hand_side_exp => #{t ? t.to_js: t}"
}
t
end
+ # 11.2
+ #
+ # NewExpression :
+ # MemberExpression
+ # new NewExpression
+ #
+ # NOTE:
+ #
+ # The NewExpression only matchs no-arguments-constructor because
+ # member expression also has "new MemberExpression Arguments"
+ #
+ # For example,
+ #
+ # 1. new A;
+ # 2. new A[B];
+ # 3. new A.B;
+ # 4. new A.B();
+ # 5. new new B();
+ # 6. A();
+ #
+ # 1 to 3 are NewExpression.
+ # 4 is MemberExpression.
+ # 5 's first new is NewExpression and second one is MemberExpression.
+ # 6 is CallExpression
+ #
+ # NewExpression can be rewritten as follows:
+ #
+ # NewExpression:
+ # MemberExpression [lookahead ∉ {(}]
+ # new NewExpression [lookahead ∉ {(}]
+ #
def new_exp(lex, context, options)
- lex.eval_lit{
- if lex.match_lit(ECMA262::ID_NEW)
- if a=new_exp(lex, context, options)
+ lex.eval_lit {
+ if lex.eql_lit?(ECMA262::ID_NEW)
+ if a = new_exp(lex, context, options)
+ if lex.eql_lit? ECMA262::PUNC_LPARENTHESIS
+ # minjs evaluate CallExpression first, so
+ # program never falls to here.
+ next nil # this is not NewExpression, may be MemberExpression.
+ end
+ #puts "new_exp> #{a.to_js}"
ECMA262::ExpNew.new(a, nil)
else
+ # minjs evaluate CallExpression first, so
+ # raise exception when program falls to here.
raise ParseError.new("unexpceted token", lex)
+ #nil
end
- else
- nil
end
- } or lex.eval_lit{
- member_exp(lex, context, options)
- }
+ } || member_exp(lex, context, options)
+ # minjs evaluate CallExpression first, so
+ # there is no reason to check parenthesis.
+ #
+ # lex.eval_lit{
+ # t = member_exp(lex, context, options)
+ # if lex.eql_lit? ECMA262::PUNC_LPARENTHESIS
+ # break nil
+ # end
+ # t
+ # }
end
-
+ # 11.2
#
- # call
+ # CallExpression :
+ # MemberExpression Arguments
+ # CallExpression Arguments
+ # CallExpression [ Expression ]
+ # CallExpression . IdentifierName
#
- # member_exp arguments
- #
- # call_exp arguments
- # call_exp [exp]
- # call_exp . identifier_name
- #
- #
def call_exp(lex, context, options)
- a = lex.eval_lit{
- if f = member_exp(lex, context, options)
- if b = arguments(lex, context, options)
- ECMA262::ExpCall.new(f, b)
- else
- f
- end
+ if a = member_exp(lex, context, options)
+ if b = arguments(lex, context, options)
+ t = ECMA262::ExpCall.new(a, b)
+ # if b is nil, this may be MemberExpression of NewExpression
else
- nil
+ return a
end
- }
- return nil if a.nil?
+ else
+ return nil
+ end
- t = a
-
- lex.eval_lit{
- while true
- if b=arguments(lex, context, options)
- t = ECMA262::ExpCall.new(t, b)
- elsif lex.match_lit(ECMA262::PUNC_LSQBRAC)
- if b=exp(lex, context, options) and lex.match_lit(ECMA262::PUNC_RSQBRAC)
- t = ECMA262::ExpPropBrac.new(t, b)
- else
- raise ParseError.new("unexpceted token", lex)
- end
- elsif lex.match_lit(ECMA262::PUNC_PERIOD)
- if (b=lex.fwd_lit()).kind_of?(ECMA262::IdentifierName)
- t = ECMA262::ExpProp.new(t, b)
- else
- raise ParseError.new("unexpceted token", lex)
- end
+ while true
+ if b = arguments(lex, context, options)
+ t = ECMA262::ExpCall.new(t, b)
+ elsif lex.eql_lit?(ECMA262::PUNC_LSQBRAC)
+ if b=exp(lex, context, options) and lex.eql_lit?(ECMA262::PUNC_RSQBRAC)
+ t = ECMA262::ExpPropBrac.new(t, b)
else
- break
+ raise ParseError.new("unexpceted token", lex)
end
+ elsif lex.eql_lit?(ECMA262::PUNC_PERIOD)
+ if (b=lex.fwd_lit(nil)).kind_of?(ECMA262::IdentifierName)
+ t = ECMA262::ExpProp.new(t, b)
+ else
+ raise ParseError.new("unexpceted token", lex)
+ end
+ else
+ break
end
- t
- } or a
+ end
+ t
end
+ # 11.2
#
- # member_exp
- # primary_exp
- # function_exp
- # new member_exp arguments
+ # MemberExpression :
+ # PrimaryExpression
+ # FunctionExpression
+ # MemberExpression [ Expression ]
+ # MemberExpression . IdentifierName
+ # new MemberExpression Arguments
#
- # member_exp[exp]
- # member_exp.identifier_name #prop(a,b)
- #
def member_exp(lex, context, options)
- a = lex.eval_lit {
- primary_exp(lex, context, options)
- } || lex.eval_lit {
- func_exp(lex, context)
- } || lex.eval_lit {
- if lex.match_lit(ECMA262::ID_NEW) and a=member_exp(lex, context, options) and b=arguments(lex, context, options)
- ECMA262::ExpNew.new(a, b)
- else
- nil
+ t = lex.eval_lit{
+ if lex.eql_lit? ECMA262::ID_NEW
+ if a = member_exp(lex, context, options)
+ b = arguments(lex, context, options)
+ # if b is nil, this may be NewExpression
+ if b
+ s = b.collect{|x| x.to_js}.join(',');
+ #puts "member_exp> [new] #{a.to_js} (#{s})"
+ next ECMA262::ExpNew.new(a, b)
+ else
+ return nil
+ end
+ else
+ return nil
+ end
end
- }
- return nil if a.nil?
+ } || primary_exp(lex, context, options) || func_exp(lex, context)
+ return nil if t.nil?
- t = a
-
- lex.eval_lit {
- while true
- if lex.match_lit(ECMA262::PUNC_LSQBRAC)
- if b=exp(lex, context, options) and lex.match_lit(ECMA262::PUNC_RSQBRAC)
- t = ECMA262::ExpPropBrac.new(t, b)
- else
- raise ParseError.new("unexpceted token", lex)
- end
- elsif lex.match_lit(ECMA262::PUNC_PERIOD)
- if (b=lex.fwd_lit()).kind_of?(ECMA262::IdentifierName)
- t = ECMA262::ExpProp.new(t, b)
- else
- raise ParseError.new("unexpceted token", lex)
- end
+ while true
+ if lex.eql_lit?(ECMA262::PUNC_LSQBRAC)
+ if b=exp(lex, context, options) and lex.eql_lit?(ECMA262::PUNC_RSQBRAC)
+ t = ECMA262::ExpPropBrac.new(t, b)
else
- break
+ raise ParseError.new("unexpceted token", lex)
end
+ elsif lex.eql_lit?(ECMA262::PUNC_PERIOD)
+ if (b=lex.fwd_lit(nil)).kind_of?(ECMA262::IdentifierName)
+ t = ECMA262::ExpProp.new(t, b)
+ else
+ raise ParseError.new("unexpceted token", lex)
+ end
+ else
+ break
end
- t
- } or a
+ end
+ t
end
-
+ # 11.2
+ # Arguments :
+ # ( )
+ # ( ArgumentList )
+ #
def arguments(lex, context, options)
- lex.eval_lit{
- return nil if lex.match_lit(ECMA262::PUNC_LPARENTHESIS).nil?
- next [] if lex.match_lit(ECMA262::PUNC_RPARENTHESIS)
- args = []
- while true
- if t = assignment_exp(lex, context, options)
- args.push(t)
- else
- return
- end
- if lex.match_lit(ECMA262::PUNC_COMMA)
- ;
- elsif lex.match_lit(ECMA262::PUNC_RPARENTHESIS)
- break
- else
- return
- end
+ return nil if lex.eql_lit?(ECMA262::PUNC_LPARENTHESIS).nil?
+ return [] if lex.eql_lit?(ECMA262::PUNC_RPARENTHESIS)
+
+ args = []
+ while true
+ if t = assignment_exp(lex, context, options)
+ args.push(t)
+ else
+ raise ParseError.new("unexpected token", lex)
end
- args
- }
+ if lex.eql_lit?(ECMA262::PUNC_COMMA)
+ ;
+ elsif lex.eql_lit?(ECMA262::PUNC_RPARENTHESIS)
+ break
+ else
+ raise ParseError.new("unexpected token", lex)
+ end
+ end
+ args
end
#
# 11.3
#
def postfix_exp(lex, context, options)
- t = lex.eval_lit{
- a = left_hand_side_exp(lex, context, options)
- return nil if a.nil?
- if punc = (lex.match_lit(ECMA262::PUNC_INC, :nolt => true) ||
- lex.match_lit(ECMA262::PUNC_DEC, :nolt => true))
- if punc == ECMA262::PUNC_INC
- ECMA262::ExpPostInc.new(a)
- else
- ECMA262::ExpPostDec.new(a)
- end
+ exp = left_hand_side_exp(lex, context, options)
+ return nil if exp.nil?
+ if punc = (lex.eql_lit_nolt?(ECMA262::PUNC_INC) ||
+ lex.eql_lit_nolt?(ECMA262::PUNC_DEC))
+ if punc == ECMA262::PUNC_INC
+ ECMA262::ExpPostInc.new(exp)
else
- a
+ ECMA262::ExpPostDec.new(exp)
end
- }
- t
+ else
+ exp
+ end
end
#
# 11.4
#
def unary_exp(lex, context, options)
- lex.eval_lit{
- if punc = (lex.match_lit(ECMA262::ID_DELETE) ||
- lex.match_lit(ECMA262::ID_VOID) ||
- lex.match_lit(ECMA262::ID_TYPEOF) ||
- lex.match_lit(ECMA262::PUNC_INC) ||
- lex.match_lit(ECMA262::PUNC_DEC) ||
- lex.match_lit(ECMA262::PUNC_ADD) ||
- lex.match_lit(ECMA262::PUNC_SUB) ||
- lex.match_lit(ECMA262::PUNC_NOT) ||
- lex.match_lit(ECMA262::PUNC_LNOT))
- a = unary_exp(lex, context, options)
- if a.nil?
- raise ParseError.new("unexpceted token", lex)
- elsif punc.val == :delete
- ECMA262::ExpDelete.new(a)
- elsif punc.val == :void
- ECMA262::ExpVoid.new(a)
- elsif punc.val == :typeof
- ECMA262::ExpTypeof.new(a)
- elsif punc == ECMA262::PUNC_INC
- ECMA262::ExpPreInc.new(a)
- elsif punc == ECMA262::PUNC_DEC
- ECMA262::ExpPreDec.new(a)
- elsif punc == ECMA262::PUNC_ADD
- ECMA262::ExpPositive.new(a)
- elsif punc == ECMA262::PUNC_SUB
- ECMA262::ExpNegative.new(a)
- elsif punc == ECMA262::PUNC_NOT
- ECMA262::ExpBitwiseNot.new(a)
- elsif punc == ECMA262::PUNC_LNOT
- ECMA262::ExpLogicalNot.new(a)
- end
+ if punc = (lex.eql_lit?(ECMA262::ID_DELETE) ||
+ lex.eql_lit?(ECMA262::ID_VOID) ||
+ lex.eql_lit?(ECMA262::ID_TYPEOF) ||
+ lex.eql_lit?(ECMA262::PUNC_INC) ||
+ lex.eql_lit?(ECMA262::PUNC_DEC) ||
+ lex.eql_lit?(ECMA262::PUNC_ADD) ||
+ lex.eql_lit?(ECMA262::PUNC_SUB) ||
+ lex.eql_lit?(ECMA262::PUNC_NOT) ||
+ lex.eql_lit?(ECMA262::PUNC_LNOT))
+ exp = unary_exp(lex, context, options)
+ if exp.nil?
+ raise ParseError.new("unexpceted token", lex)
+ elsif punc == ECMA262::PUNC_INC
+ ECMA262::ExpPreInc.new(exp)
+ elsif punc == ECMA262::PUNC_DEC
+ ECMA262::ExpPreDec.new(exp)
+ elsif punc == ECMA262::PUNC_ADD
+ ECMA262::ExpPositive.new(exp)
+ elsif punc == ECMA262::PUNC_SUB
+ ECMA262::ExpNegative.new(exp)
+ elsif punc == ECMA262::PUNC_NOT
+ ECMA262::ExpBitwiseNot.new(exp)
+ elsif punc == ECMA262::PUNC_LNOT
+ ECMA262::ExpLogicalNot.new(exp)
+ elsif punc.respond_to?(:val)
+ if punc.val == :delete
+ ECMA262::ExpDelete.new(exp)
+ elsif punc.val == :void
+ ECMA262::ExpVoid.new(exp)
+ elsif punc.val == :typeof
+ ECMA262::ExpTypeof.new(exp)
+ end
end
- } || lex.eval_lit{
+ else
postfix_exp(lex, context, options)
- }
+ end
end
#
# 11.5
#
def multiplicative_exp(lex, context, options)
- lex.eval_lit {
- a = unary_exp(lex, context, options)
- next nil if !a
- t = a
- while punc = lex.match_lit(ECMA262::PUNC_MUL) ||
- lex.match_lit(ECMA262::PUNC_DIV, :hint => :div) ||
- lex.match_lit(ECMA262::PUNC_MOD)
+ a = unary_exp(lex, context, options)
+ return nil if !a
+ t = a
+ while punc = lex.eql_lit?(ECMA262::PUNC_MUL) ||
+ lex.eql_lit?(ECMA262::PUNC_DIV, :div) ||
+ lex.eql_lit?(ECMA262::PUNC_MOD)
- if b = unary_exp(lex, context, options)
- if punc == ECMA262::PUNC_MUL
- t = ECMA262::ExpMul.new(t, b)
- elsif punc == ECMA262::PUNC_DIV
- t = ECMA262::ExpDiv.new(t, b)
- else
- t = ECMA262::ExpMod.new(t, b)
- end
+ if b = unary_exp(lex, context, options)
+ if punc == ECMA262::PUNC_MUL
+ t = ECMA262::ExpMul.new(t, b)
+ elsif punc == ECMA262::PUNC_DIV
+ t = ECMA262::ExpDiv.new(t, b)
else
- raise ParseError.new("unexpceted token", lex)
+ t = ECMA262::ExpMod.new(t, b)
end
+ else
+ raise ParseError.new("unexpceted token", lex)
end
- t
- }
+ end
+ t
end
#
# 11.6
#
def additive_exp(lex, context, options)
- lex.eval_lit {
- a = multiplicative_exp(lex, context, options)
- next nil if !a
+ a = multiplicative_exp(lex, context, options)
+ return nil if !a
- t = a
- while punc = lex.match_lit(ECMA262::PUNC_ADD) || lex.match_lit(ECMA262::PUNC_SUB)
- if b = multiplicative_exp(lex, context, options)
- if punc == ECMA262::PUNC_ADD
- t = ECMA262::ExpAdd.new(t, b)
- else
- t = ECMA262::ExpSub.new(t, b)
- end
+ t = a
+ while punc = lex.eql_lit?(ECMA262::PUNC_ADD) || lex.eql_lit?(ECMA262::PUNC_SUB)
+ if b = multiplicative_exp(lex, context, options)
+ if punc == ECMA262::PUNC_ADD
+ t = ECMA262::ExpAdd.new(t, b)
else
- raise ParseError.new("unexpceted token", lex)
+ t = ECMA262::ExpSub.new(t, b)
end
+ else
+ raise ParseError.new("unexpceted token", lex)
end
-
- t
- }
+ end
+ t
end
#
# 11.7
def shift_exp(lex, context, options)
- lex.eval_lit {
- a = additive_exp(lex, context, options)
- next nil if !a
+ a = additive_exp(lex, context, options)
+ return nil if !a
- t = a
- while punc = lex.match_lit(ECMA262::PUNC_LSHIFT) ||
- lex.match_lit(ECMA262::PUNC_RSHIFT) ||
- lex.match_lit(ECMA262::PUNC_URSHIFT)
- if b = additive_exp(lex, context, options)
- if punc == ECMA262::PUNC_LSHIFT
- t = ECMA262::ExpLShift.new(t, b)
- elsif punc == ECMA262::PUNC_RSHIFT
- t = ECMA262::ExpRShift.new(t, b)
- elsif punc == ECMA262::PUNC_URSHIFT
- t = ECMA262::ExpURShift.new(t, b)
- end
- else
- raise ParseError.new("unexpceted token", lex)
+ t = a
+ while punc = lex.eql_lit?(ECMA262::PUNC_LSHIFT) ||
+ lex.eql_lit?(ECMA262::PUNC_RSHIFT) ||
+ lex.eql_lit?(ECMA262::PUNC_URSHIFT)
+ if b = additive_exp(lex, context, options)
+ if punc == ECMA262::PUNC_LSHIFT
+ t = ECMA262::ExpLShift.new(t, b)
+ elsif punc == ECMA262::PUNC_RSHIFT
+ t = ECMA262::ExpRShift.new(t, b)
+ elsif punc == ECMA262::PUNC_URSHIFT
+ t = ECMA262::ExpURShift.new(t, b)
end
+ else
+ raise ParseError.new("unexpceted token", lex)
end
- t
- }
+ end
+ t
end
#
#
# 11.8
#
def relational_exp(lex, context, options)
- lex.eval_lit {
- a = shift_exp(lex, context, options)
- next nil if !a
+ a = shift_exp(lex, context, options)
+ return nil if !a
- t = a
- while (punc = lex.match_lit(ECMA262::PUNC_LT) || lex.match_lit(ECMA262::PUNC_GT) ||
- lex.match_lit(ECMA262::PUNC_LTEQ) || lex.match_lit(ECMA262::PUNC_GTEQ) ||
- lex.match_lit(ECMA262::ID_INSTANCEOF) || (!options[:no_in] && lex.match_lit(ECMA262::ID_IN)))
- if b = shift_exp(lex, context, options)
- if punc == ECMA262::PUNC_LT
- t = ECMA262::ExpLt.new(t, b)
- elsif punc == ECMA262::PUNC_GT
- t = ECMA262::ExpGt.new(t, b)
- elsif punc == ECMA262::PUNC_LTEQ
- t = ECMA262::ExpLtEq.new(t, b)
- elsif punc == ECMA262::PUNC_GTEQ
- t = ECMA262::ExpGtEq.new(t, b)
- elsif punc.val == :instanceof
- t = ECMA262::ExpInstanceOf.new(t, b)
- elsif !options[:no_in] and punc.val == :in
- t = ECMA262::ExpIn.new(t, b)
- else
- end
+ t = a
+ while (punc = lex.eql_lit?(ECMA262::PUNC_LT) || lex.eql_lit?(ECMA262::PUNC_GT) ||
+ lex.eql_lit?(ECMA262::PUNC_LTEQ) || lex.eql_lit?(ECMA262::PUNC_GTEQ) ||
+ lex.eql_lit?(ECMA262::ID_INSTANCEOF) || (!options[:no_in] && lex.eql_lit?(ECMA262::ID_IN)))
+ if b = shift_exp(lex, context, options)
+ if punc == ECMA262::PUNC_LT
+ t = ECMA262::ExpLt.new(t, b)
+ elsif punc == ECMA262::PUNC_GT
+ t = ECMA262::ExpGt.new(t, b)
+ elsif punc == ECMA262::PUNC_LTEQ
+ t = ECMA262::ExpLtEq.new(t, b)
+ elsif punc == ECMA262::PUNC_GTEQ
+ t = ECMA262::ExpGtEq.new(t, b)
+ elsif punc.val == :instanceof
+ t = ECMA262::ExpInstanceOf.new(t, b)
+ elsif !options[:no_in] and punc.val == :in
+ t = ECMA262::ExpIn.new(t, b)
else
- raise ParseError.new("unexpceted token", lex)
end
+ else
+ raise ParseError.new("unexpceted token", lex)
end
-
- t
- }
+ end
+ t
end
#
#
# 11.9
# a == b
# a != b
# a === b
# a !== b
#
def equality_exp(lex, context, options)
- lex.eval_lit {
- a = relational_exp(lex, context, options)
- next nil if !a
+ a = relational_exp(lex, context, options)
+ return nil if !a
- t = a
- while punc = lex.match_lit(ECMA262::PUNC_EQ) ||
- lex.match_lit(ECMA262::PUNC_NEQ) ||
- lex.match_lit(ECMA262::PUNC_SEQ) ||
- lex.match_lit(ECMA262::PUNC_SNEQ)
- if b = relational_exp(lex, context, options)
- if punc == ECMA262::PUNC_EQ
- t = ECMA262::ExpEq.new(t, b)
- elsif punc == ECMA262::PUNC_NEQ
- t = ECMA262::ExpNotEq.new(t, b)
- elsif punc == ECMA262::PUNC_SEQ
- t = ECMA262::ExpStrictEq.new(t, b)
- elsif punc == ECMA262::PUNC_SNEQ
- t = ECMA262::ExpStrictNotEq.new(t, b)
- end
- else
- raise ParseError.new("unexpceted token", lex)
+ t = a
+ while punc = lex.eql_lit?(ECMA262::PUNC_EQ) ||
+ lex.eql_lit?(ECMA262::PUNC_NEQ) ||
+ lex.eql_lit?(ECMA262::PUNC_SEQ) ||
+ lex.eql_lit?(ECMA262::PUNC_SNEQ)
+ if b = relational_exp(lex, context, options)
+ if punc == ECMA262::PUNC_EQ
+ t = ECMA262::ExpEq.new(t, b)
+ elsif punc == ECMA262::PUNC_NEQ
+ t = ECMA262::ExpNotEq.new(t, b)
+ elsif punc == ECMA262::PUNC_SEQ
+ t = ECMA262::ExpStrictEq.new(t, b)
+ elsif punc == ECMA262::PUNC_SNEQ
+ t = ECMA262::ExpStrictNotEq.new(t, b)
end
+ else
+ raise ParseError.new("unexpceted token", lex)
end
-
- t
- }
+ end
+ t
end
#
# 11.10
# a & b
#
def bitwise_and_exp(lex, context, options)
- lex.eval_lit {
- a = equality_exp(lex, context, options)
- next nil if !a
+ a = equality_exp(lex, context, options)
+ return nil if !a
- t = a
- while punc = lex.match_lit(ECMA262::PUNC_AND)
- if b = equality_exp(lex, context, options)
- t = ECMA262::ExpAnd.new(t, b)
- else
- raise ParseError.new("unexpceted token", lex)
- end
+ t = a
+ while punc = lex.eql_lit?(ECMA262::PUNC_AND)
+ if b = equality_exp(lex, context, options)
+ t = ECMA262::ExpAnd.new(t, b)
+ else
+ raise ParseError.new("unexpceted token", lex)
end
-
- t
- }
+ end
+ t
end
#
# a ^ b
#
def bitwise_xor_exp(lex, context, options)
- lex.eval_lit {
- a = bitwise_and_exp(lex, context, options)
- next nil if !a
+ a = bitwise_and_exp(lex, context, options)
+ return nil if !a
- t = a
- while punc = lex.match_lit(ECMA262::PUNC_XOR)
- if b = bitwise_and_exp(lex, context, options)
- t = ECMA262::ExpXor.new(t, b)
- else
- raise ParseError.new("unexpceted token", lex)
- end
+ t = a
+ while punc = lex.eql_lit?(ECMA262::PUNC_XOR)
+ if b = bitwise_and_exp(lex, context, options)
+ t = ECMA262::ExpXor.new(t, b)
+ else
+ raise ParseError.new("unexpceted token", lex)
end
+ end
- t
- }
+ t
end
#
# a | b
#
def bitwise_or_exp(lex, context, options)
- lex.eval_lit {
- a = bitwise_xor_exp(lex, context, options)
- next nil if !a
+ a = bitwise_xor_exp(lex, context, options)
+ return nil if !a
- t = a
- while punc = lex.match_lit(ECMA262::PUNC_OR)
- if b = bitwise_xor_exp(lex, context, options)
- t = ECMA262::ExpOr.new(t, b)
- else
- raise ParseError.new("unexpceted token", lex)
- end
+ t = a
+ while punc = lex.eql_lit?(ECMA262::PUNC_OR)
+ if b = bitwise_xor_exp(lex, context, options)
+ t = ECMA262::ExpOr.new(t, b)
+ else
+ raise ParseError.new("unexpceted token", lex)
end
-
- t
- }
+ end
+ t
end
#
# 11.11
# a && b
#
def logical_and_exp(lex, context, options)
- lex.eval_lit {
- a = bitwise_or_exp(lex, context, options)
- next nil if !a
+ a = bitwise_or_exp(lex, context, options)
+ return nil if !a
- t = a
- while punc = lex.match_lit(ECMA262::PUNC_LAND)
- if b = bitwise_or_exp(lex, context, options)
- t = ECMA262::ExpLogicalAnd.new(t, b)
- else
- raise ParseError.new("unexpceted token", lex)
- end
+ t = a
+ while punc = lex.eql_lit?(ECMA262::PUNC_LAND)
+ if b = bitwise_or_exp(lex, context, options)
+ t = ECMA262::ExpLogicalAnd.new(t, b)
+ else
+ raise ParseError.new("unexpceted token", lex)
end
+ end
- t
- }
+ t
end
def logical_or_exp(lex, context, options)
- lex.eval_lit {
- a = logical_and_exp(lex, context, options)
- next nil if !a
+ a = logical_and_exp(lex, context, options)
+ return nil if !a
- t = a
- while punc = lex.match_lit(ECMA262::PUNC_LOR)
- if b = logical_and_exp(lex, context, options)
- t = ECMA262::ExpLogicalOr.new(t, b)
- else
- raise ParseError.new("unexpceted token", lex)
- end
+ t = a
+ while punc = lex.eql_lit?(ECMA262::PUNC_LOR)
+ if b = logical_and_exp(lex, context, options)
+ t = ECMA262::ExpLogicalOr.new(t, b)
+ else
+ raise ParseError.new("unexpceted token", lex)
end
+ end
- t
- }
+ t
end
#
# 11.12
# a ? b : c
#
def cond_exp(lex, context, options)
- t = lex.eval_lit {
- a = logical_or_exp(lex, context, options)
- next nil if !a
+ a = logical_or_exp(lex, context, options)
+ return nil if !a
- if lex.match_lit(ECMA262::PUNC_CONDIF)
- if b=assignment_exp(lex, context, options) and lex.match_lit(ECMA262::PUNC_CONDELSE) and c=assignment_exp(lex, context, options)
- ECMA262::ExpCond.new(a, b, c)
- else
- raise ParseError.new("unexpceted token", lex)
- end
+ if lex.eql_lit?(ECMA262::PUNC_CONDIF)
+ if b=assignment_exp(lex, context, options) and lex.eql_lit?(ECMA262::PUNC_COLON) and c=assignment_exp(lex, context, options)
+ ECMA262::ExpCond.new(a, b, c)
else
- a
+ raise ParseError.new("unexpceted token", lex)
end
- }
- t
+ else
+ a
+ end
end
#
#11.13
+ # AssignmentExpression :
+ # ConditionalExpression
+ # LeftHandSideExpression = AssignmentExpression
+ # LeftHandSideExpression AssignmentOperator AssignmentExpression
#
def assignment_exp(lex, context, options)
@logger.debug "*** assignment_exp"
- left_hand = nil
t = cond_exp(lex, context, options)
return nil if t.nil?
- lex.eval_lit {
- left_hand = t
- punc = lex.next_lit
- if punc == ECMA262::PUNC_LET ||
- punc == ECMA262::PUNC_DIVLET ||
- punc == ECMA262::PUNC_MULLET ||
- punc == ECMA262::PUNC_MODLET ||
- punc == ECMA262::PUNC_ADDLET ||
- punc == ECMA262::PUNC_SUBLET ||
- punc == ECMA262::PUNC_LSHIFTLET ||
- punc == ECMA262::PUNC_RSHIFTLET ||
- punc == ECMA262::PUNC_URSHIFTLET ||
- punc == ECMA262::PUNC_ANDLET ||
- punc == ECMA262::PUNC_ORLET ||
- punc == ECMA262::PUNC_XORLET
- lex.fwd_lit
- if b = assignment_exp(lex, context, options)
- case punc
- when ECMA262::PUNC_LET
- ECMA262::ExpAssign.new(left_hand, b)
- when ECMA262::PUNC_DIVLET
- ECMA262::ExpDivAssign.new(left_hand, b)
- when ECMA262::PUNC_MULLET
- ECMA262::ExpMulAssign.new(left_hand, b)
- when ECMA262::PUNC_MODLET
- ECMA262::ExpModAssign.new(left_hand, b)
- when ECMA262::PUNC_ADDLET
- ECMA262::ExpAddAssign.new(left_hand, b)
- when ECMA262::PUNC_SUBLET
- ECMA262::ExpSubAssign.new(left_hand, b)
- when ECMA262::PUNC_LSHIFTLET
- ECMA262::ExpLShiftAssign.new(left_hand, b)
- when ECMA262::PUNC_RSHIFTLET
- ECMA262::ExpRShiftAssign.new(left_hand, b)
- when ECMA262::PUNC_URSHIFTLET
- ECMA262::ExpURShiftAssign.new(left_hand, b)
- when ECMA262::PUNC_ANDLET
- ECMA262::ExpAndAssign.new(left_hand, b)
- when ECMA262::PUNC_ORLET
- ECMA262::ExpOrAssign.new(left_hand, b)
- when ECMA262::PUNC_XORLET
- ECMA262::ExpXorAssign.new(left_hand, b)
- else
- raise "internal error"
- end
+
+ if !t.left_hand_side_exp?
+ return t
+ end
+ left_hand = t
+ punc = lex.peek_lit(:div)
+ if punc == ECMA262::PUNC_LET ||
+ punc == ECMA262::PUNC_DIVLET ||
+ punc == ECMA262::PUNC_MULLET ||
+ punc == ECMA262::PUNC_MODLET ||
+ punc == ECMA262::PUNC_ADDLET ||
+ punc == ECMA262::PUNC_SUBLET ||
+ punc == ECMA262::PUNC_LSHIFTLET ||
+ punc == ECMA262::PUNC_RSHIFTLET ||
+ punc == ECMA262::PUNC_URSHIFTLET ||
+ punc == ECMA262::PUNC_ANDLET ||
+ punc == ECMA262::PUNC_ORLET ||
+ punc == ECMA262::PUNC_XORLET
+ lex.fwd_after_peek
+ if b = assignment_exp(lex, context, options)
+ case punc
+ when ECMA262::PUNC_LET
+ ECMA262::ExpAssign.new(left_hand, b)
+ when ECMA262::PUNC_DIVLET
+ ECMA262::ExpDivAssign.new(left_hand, b)
+ when ECMA262::PUNC_MULLET
+ ECMA262::ExpMulAssign.new(left_hand, b)
+ when ECMA262::PUNC_MODLET
+ ECMA262::ExpModAssign.new(left_hand, b)
+ when ECMA262::PUNC_ADDLET
+ ECMA262::ExpAddAssign.new(left_hand, b)
+ when ECMA262::PUNC_SUBLET
+ ECMA262::ExpSubAssign.new(left_hand, b)
+ when ECMA262::PUNC_LSHIFTLET
+ ECMA262::ExpLShiftAssign.new(left_hand, b)
+ when ECMA262::PUNC_RSHIFTLET
+ ECMA262::ExpRShiftAssign.new(left_hand, b)
+ when ECMA262::PUNC_URSHIFTLET
+ ECMA262::ExpURShiftAssign.new(left_hand, b)
+ when ECMA262::PUNC_ANDLET
+ ECMA262::ExpAndAssign.new(left_hand, b)
+ when ECMA262::PUNC_ORLET
+ ECMA262::ExpOrAssign.new(left_hand, b)
+ when ECMA262::PUNC_XORLET
+ ECMA262::ExpXorAssign.new(left_hand, b)
else
- raise ParseError.new("unexpceted token", lex)
+ raise "internal error"
end
else
- @logger.debug {
- "*** assignment_exp => #{t ? t.to_js : t}"
- }
- t
+ raise ParseError.new("unexpceted token", lex)
end
- }
+ else
+ @logger.debug {
+ "*** assignment_exp => #{t ? t.to_js : t}"
+ }
+ t
+ end
end
#
# 11.14
+ # Expression :
+ # AssignmentExpression
+ # Expression , AssignmentExpression
#
def exp(lex, context, options)
@logger.debug "*** expression"
- lex.eval_lit{
- t = assignment_exp(lex, context, {:hint => :regexp}.merge(options))
- while punc = lex.match_lit(ECMA262::PUNC_COMMA)
- if b = assignment_exp(lex,context, {:hint => :regexp}.merge(options))
- t = ECMA262::ExpComma.new(t, b)
- else
- raise ParseError.new("unexpceted token", lex)
- end
+
+ t = assignment_exp(lex, context, options)
+ return nil if t.nil?
+ while punc = lex.eql_lit?(ECMA262::PUNC_COMMA)
+ if b = assignment_exp(lex,context, options)
+ t = ECMA262::ExpComma.new(t, b)
+ else
+ raise ParseError.new("unexpceted token", lex)
end
- @logger.debug{
- "*** expression => #{t ? t.to_js : t}"
- }
- t
+ end
+ @logger.debug{
+ "*** expression => #{t ? t.to_js : t}"
}
+ t
end
end
end