node/lib/metasm/metasm/parse_c.rb
def parse_value_postfix(parser, scope, val)
			tok = parser.skipspaces
			nval = \
			if tok and tok.type == :punct
				case tok.raw
				when '+', '++', '-', '--', '->'
					ntok = parser.readtok
					if (tok.raw == '+' or tok.raw == '-') and ntok and ntok.type == :punct and
							(ntok.raw == tok.raw or (tok.raw == '-' and ntok.raw == '>'))
						tok.raw << ntok.raw
					else
						parser.unreadtok ntok
					end
					case tok.raw
					when '+', '-'
						nil
					when '++', '--'
						raise parser, "#{val}: invalid lvalue" if not CExpression.lvalue?(val)
						CExpression.new(val, tok.raw.to_sym, nil, val.type)
					when '->'
						# XXX allow_bad_c..
						raise tok, "#{val}: not a pointer" if not val.type.pointer?
						type = val.type.pointed.untypedef
						raise tok, "#{val}: bad pointer" if not type.kind_of? Union
						raise tok, "#{val}: incomplete type" if not type.members
						raise tok, "#{val}: invalid member" if not tok = parser.skipspaces or tok.type != :string or not m = type.findmember(tok.raw)
						CExpression.new(val, :'->', tok.raw, m.type)
					end
				when '.'
					type = val.type.untypedef
					if not ntok = parser.skipspaces or ntok.type != :string or not type.kind_of? Union
						parser.unreadtok ntok
						nil
					else
						raise ntok, "#{val}: incomplete type" if not type.members
						raise ntok, "#{val}: invalid member" if not m = type.findmember(ntok.raw)
						CExpression.new(val, :'.', ntok.raw, m.type)
					end
				when '['
					raise tok, "#{val}: index expected" if not idx = parse(parser, scope)
					val, idx = idx, val        if not val.type.pointer?		# fake support of "4[tab]"
					raise tok, "#{val}: not a pointer" if not val.type.pointer?
					raise tok, "#{val}: invalid index"  if not idx.type.integral?
					raise tok, "#{val}: get perpendicular ! (elsewhere)" if idx.kind_of?(CExpression) and idx.op == :','
					raise tok || parser, "']' expected" if not tok = parser.skipspaces or tok.type != :punct or tok.raw != ']'
					type = val.type.untypedef.type
					# TODO boundscheck (and become king of the universe)
					CExpression.new(val, :'[]', idx, type)
				when '('
					type = val.type.untypedef
					type = type.type.untypedef if type.kind_of? Pointer
					raise tok, "#{val}: not a function" if not type.kind_of? Function

					args = []
					loop do
						a = parse(parser, scope, false)
						break if not a
						args << a
						if not ntok = parser.skipspaces or ntok.type != :punct or ntok.raw != ','
							parser.unreadtok ntok
							break
						end
					end
					raise ntok || parser, "#{val}: ')' expected" if not ntok = parser.skipspaces or ntok.type != :punct or ntok.raw != ')'

					type.args ||= []
					raise tok, "#{val}: bad argument count: #{args.length} for #{type.args.length}" if (type.varargs ? (args.length < type.args.length) : (args.length != type.args.length))
					type.args.zip(args) { |ta, a|
						p, i = ta.type.pointer?, ta.type.integral?
						r = a.reduce(parser) if p or i
						if (not p and not i) or (i and not r.kind_of? ::Integer) or (p and r != 0)
							tok = tok.dup ; tok.raw = a.to_s
							parser.check_compatible_type(tok, a.type, ta.type)
						end
					}
					CExpression.new(val, :funcall, args, type.type)
				end
			end

			if nval
				parse_value_postfix(parser, scope, nval)
			else
				parser.unreadtok tok
				val
			end
		end
# parse postfix forms (postincrement, array index, struct member dereference)
parse postfix forms (postincrement, array index, struct member dereference)
parse postfix forms ( postincrement array index struct member dereference )
def parse_value_postfix(parser, scope, val)
			tok = parser.skipspaces
			nval = \
			if tok and tok.type == :punct
				case tok.raw
				when '+', '++', '-', '--', '->'
					ntok = parser.readtok
					if (tok.raw == '+' or tok.raw == '-') and ntok and ntok.type == :punct and
							(ntok.raw == tok.raw or (tok.raw == '-' and ntok.raw == '>'))
						tok.raw << ntok.raw
					else
						parser.unreadtok ntok
					end
					case tok.raw
					when '+', '-'
						nil
					when '++', '--'
						raise parser, "#{val}: invalid lvalue" if not CExpression.lvalue?(val)
						CExpression.new(val, tok.raw.to_sym, nil, val.type)
					when '->'
						raise tok, "#{val}: not a pointer" if not val.type.pointer?
						type = val.type.pointed.untypedef
						raise tok, "#{val}: bad pointer" if not type.kind_of? Union
						raise tok, "#{val}: incomplete type" if not type.members
						raise tok, "#{val}: invalid member" if not tok = parser.skipspaces or tok.type != :string or not m = type.findmember(tok.raw)
						CExpression.new(val, :'->', tok.raw, m.type)
					end
				when '.'
					type = val.type.untypedef
					if not ntok = parser.skipspaces or ntok.type != :string or not type.kind_of? Union
						parser.unreadtok ntok
						nil
					else
						raise ntok, "#{val}: incomplete type" if not type.members
						raise ntok, "#{val}: invalid member" if not m = type.findmember(ntok.raw)
						CExpression.new(val, :'.', ntok.raw, m.type)
					end
				when '['
					raise tok, "#{val}: index expected" if not idx = parse(parser, scope)
					val, idx = idx, val        if not val.type.pointer?		
					raise tok, "#{val}: not a pointer" if not val.type.pointer?
					raise tok, "#{val}: invalid index"  if not idx.type.integral?
					raise tok, "#{val}: get perpendicular ! (elsewhere)" if idx.kind_of?(CExpression) and idx.op == :','
					raise tok || parser, "']' expected" if not tok = parser.skipspaces or tok.type != :punct or tok.raw != ']'
					type = val.type.untypedef.type
					CExpression.new(val, :'[]', idx, type)
				when '('
					type = val.type.untypedef
					type = type.type.untypedef if type.kind_of? Pointer
					raise tok, "#{val}: not a function" if not type.kind_of? Function
					args = []
					loop do
						a = parse(parser, scope, false)
						break if not a
						args << a
						if not ntok = parser.skipspaces or ntok.type != :punct or ntok.raw != ','
							parser.unreadtok ntok
							break
						end
					end
					raise ntok || parser, "#{val}: ')' expected" if not ntok = parser.skipspaces or ntok.type != :punct or ntok.raw != ')'
					type.args ||= []
					raise tok, "#{val}: bad argument count: #{args.length} for #{type.args.length}" if (type.varargs ? (args.length < type.args.length) : (args.length != type.args.length))
					type.args.zip(args) { |ta, a|
						p, i = ta.type.pointer?, ta.type.integral?
						r = a.reduce(parser) if p or i
						if (not p and not i) or (i and not r.kind_of? ::Integer) or (p and r != 0)
							tok = tok.dup ; tok.raw = a.to_s
							parser.check_compatible_type(tok, a.type, ta.type)
						end
					}
					CExpression.new(val, :funcall, args, type.type)
				end
			end
			if nval
				parse_value_postfix(parser, scope, nval)
			else
				parser.unreadtok tok
				val
			end
		end
def parse_value_postfix ( parser , scope , val ) tok = parser . skipspaces nval = if tok and tok . type == :punct case tok . raw when '+' , '++' , '-' , '--' , '->' ntok = parser . readtok if ( tok . raw == '+' or tok . raw == '-' ) and ntok and ntok . type == :punct and ( ntok . raw == tok . raw or ( tok . raw == '-' and ntok . raw == '>' ) ) tok . raw << ntok . raw else parser . unreadtok ntok end case tok . raw when '+' , '-' nil when '++' , '--' raise parser , "#{val}: invalid lvalue" if not CExpression . lvalue? ( val ) CExpression . new ( val , tok . raw . to_sym , nil , val . type ) when '->' raise tok , "#{val}: not a pointer" if not val . type . pointer? type = val . type . pointed . untypedef raise tok , "#{val}: bad pointer" if not type . kind_of? Union raise tok , "#{val}: incomplete type" if not type . members raise tok , "#{val}: invalid member" if not tok = parser . skipspaces or tok . type != :string or not m = type . findmember ( tok . raw ) CExpression . new ( val , :' -> ' , tok . raw , m . type ) end when '.' type = val . type . untypedef if not ntok = parser . skipspaces or ntok . type != :string or not type . kind_of? Union parser . unreadtok ntok nil else raise ntok , "#{val}: incomplete type" if not type . members raise ntok , "#{val}: invalid member" if not m = type . findmember ( ntok . raw ) CExpression . new ( val , :' . ' , ntok . raw , m . type ) end when '[' raise tok , "#{val}: index expected" if not idx = parse ( parser , scope ) val , idx = idx , val if not val . type . pointer? raise tok , "#{val}: not a pointer" if not val . type . pointer? raise tok , "#{val}: invalid index" if not idx . type . integral? raise tok , "#{val}: get perpendicular ! (elsewhere)" if idx . kind_of? ( CExpression ) and idx . op == :' , ' raise tok || parser , "']' expected" if not tok = parser . skipspaces or tok . type != :punct or tok . raw != ']' type = val . type . untypedef . type CExpression . new ( val , :' [] ' , idx , type ) when '(' type = val . type . untypedef type = type . type . untypedef if type . kind_of? Pointer raise tok , "#{val}: not a function" if not type . kind_of? Function args = [ ] loop do a = parse ( parser , scope , false ) break if not a args << a if not ntok = parser . skipspaces or ntok . type != :punct or ntok . raw != ',' parser . unreadtok ntok break end end raise ntok || parser , "#{val}: ')' expected" if not ntok = parser . skipspaces or ntok . type != :punct or ntok . raw != ')' type . args ||= [ ] raise tok , "#{val}: bad argument count: #{args.length} for #{type.args.length}" if ( type . varargs ? ( args . length < type . args . length ) : ( args . length != type . args . length ) ) type . args . zip ( args ) { | ta , a | p , i = ta . type . pointer? , ta . type . integral? r = a . reduce ( parser ) if p or i if ( not p and not i ) or ( i and not r . kind_of? :: Integer ) or ( p and r != 0 ) tok = tok . dup ; tok . raw = a . to_s parser . check_compatible_type ( tok , a . type , ta . type ) end } CExpression . new ( val , :funcall , args , type . type ) end end if nval parse_value_postfix ( parser , scope , nval ) else parser . unreadtok tok val end end
parse postfix forms (postincrement, array index, struct member dereference)
parse postfix forms ( postincrement array index struct member dereference )
# XXX allow_bad_c.. # fake support of "4[tab]" # TODO boundscheck (and become king of the universe)
parser
scope
val