/// <summary>
    /// function_modifier
    ///   : '(' [parameter_type_list] ')'
    /// </summary>
    public static Int32 ParseFunctionModifier(List<Token> src, Int32 begin, out FunctionModifier modifier)
    {
        // match '('
        if (!Parser.EatOperator(src, ref begin, OperatorVal.LPAREN)) {
            modifier = null;
            return -1;
        }

        // match constant_expression, if fail, just assume no parameter
        ParameterTypeList param_type_list;
        Int32 saved = begin;
        if ((begin = _parameter_type_list.Parse(src, begin, out param_type_list)) == -1) {
            param_type_list = new ParameterTypeList(new List<ParamDecln>());
            begin = saved;
        }

        // match ')'
        if (!Parser.EatOperator(src, ref begin, OperatorVal.RPAREN)) {
            modifier = null;
            return -1;
        }

        modifier = new FunctionModifier(param_type_list.params_inner_declns, param_type_list.params_varargs);
        return begin;
    }
    public static Int32 Parse(List<Token> src, Int32 begin, out ParameterTypeList param_type_list)
    {
        return Parser.ParseSequence(
            src, begin, out param_type_list,

            // parameter_list
            _parameter_list.Parse,

            // [ ',' '...' ]?
            ParseOptionalVarArgs,

            (List<ParamDecln> param_list, Boolean is_varargs) => new ParameterTypeList(param_list, is_varargs)
        );
    }
 public FunctionModifier(ParameterTypeList _param_type_list)
     : base(Kind.FUNCTION) {
     param_type_list = _param_type_list;
 }